home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / Technical Docs / MPW 411 / InsideMacintoshHelp < prev    next >
Encoding:
Text File  |  1992-02-07  |  7.2 MB  |  155,333 lines  |  [TEXT/MPS ]

Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
  1. æKY CopyrightNotice
  2. æC  Copyright Apple Computer, Inc. 1985-1990, All rights reserved.
  3. 411 - Inside Macintosh Help - MPW 3.2 Final Release.
  4. Friday, March 29,1991 9:00:00 AM
  5.  
  6. Information source: SpInsideMacintosh 1.0 HyperCard stack.
  7.                     Pegasus 1.2.5 Hypercard Stack  IM Vol VI
  8.                     Inside Macintosh Volume VI Hypercard Stack
  9. æKY Help
  10. InsideMacintoshHelp
  11. æC 
  12. AboutInsideMacintoshHelp   Preface                   UserInterfaceGuidelines
  13. IntroductionToSystem7.0    RoadMap                   WorldwideSoftwareOverview
  14.                                                      
  15.                      
  16. AliasManager               FontManager               QuickDraw
  17. AppleEventManager          GraphicsDevicesManager    ResourceManager
  18. AppleTalkManager           HelpManager               ScrapManager
  19. ColorManager               ListManager               ScriptManager
  20. ControlManager             MemoryManager             SCSIManager
  21. DataAccessManager          MenuManager               ShutdownManager
  22. DeferredTaskManager        NotificationManager       SlotManager     
  23. DeskManager                OSEventManager            SoundManager 
  24. DeviceManager              PackageManager            StartManager
  25. DialogManager              PaletteManager            TimeManager 
  26. EditionManager             PowerManager              ToolboxEventManager 
  27. EventManager               PrintingManager           VerticalRetraceManager 
  28. FileManager                ProcessManagement         WindowManager
  29.  
  30.  
  31.  
  32. AppleDesktopBus            FloatingPointPackage      SerialDrivers                   
  33. BinaryDecimalConversion    GraphicsOverView          SoundDriver
  34. ColorPickerPackage         InternationalUtilities    StandardFilePackage      
  35. ColorQuickDraw             MacintoshHardware         SystemErrorHandler 
  36. CompatibilityGuidelines    MemoryManagement          SystemResourceFile
  37. ControlPanels              OSUtilities               TextEdit
  38. DiskDriver                 PictureUtilitiesPackage   ToolboxUtilities
  39. DiskInitialization         PPCToolbox                UsingAssemblyLanguage             
  40. FinderInterface            SegmentLoader                                          
  41.  
  42.  
  43. A.ResultCodes              C.SystemTraps             SystemErrors
  44. B.MovesMemory              D.GlobalVariables         Glossary
  45.  
  46. æKY AboutInsideMacintoshHelp
  47. æC
  48.  
  49. ------------------------------------------------------------------------------
  50.  Version 1.0 Final  
  51.  
  52.  Shipped with MPW 3.2 Final and System 7.0 Final CD releases.
  53.  Includes the latest changes to InsideMacintosh VI document.
  54.  
  55. ------------------------------------------------------------------------------
  56.  Version 1.0 B2 
  57.  
  58.  Shipped on the ETO#3 CD release and System 7.0 B4 CD Release.
  59.  This version has more current Volume VI information. 
  60.  
  61.  
  62. ------------------------------------------------------------------------------
  63.  Version 1.0 B1:
  64.  
  65.  Volume VI chapters have been added to this version which contain information
  66.  about System 7.0, new managers and changes to previous ones. 
  67.  
  68.  New manager chapters are:               
  69.     AppleTalk Manager                                             
  70.     Edition Manager
  71.     Event Manager
  72.     GraphicDevices Manager (Replaces the Graphic Devices chapter in Volume V) 
  73.     Help Manager
  74.     Memory Management
  75.     Power Manager
  76.     PPC Toolbox
  77.     Process Management
  78.  
  79. Changed chapters are:
  80.     Alias Manager 
  81.     Color Picker Package
  82.     Color Quikdraw
  83.     Control Panels
  84.     File Manager
  85.     FinderInterface
  86.     Font Manager
  87.     Notification Manager
  88.     Palette Manager
  89.     Resource Manager
  90.     Slot Manager
  91.     Sound Manager
  92.     TextEdit
  93.     Time Manager
  94.     
  95. New/changed documentation chapters are:
  96.     Compatibility Guidelines
  97.     Graphics Overview
  98.     Introduction to System 7.0
  99.     Preface
  100.     UserInterface Guidelines VI
  101.     Worldwide Software Overview
  102.  
  103. ------------------------------------------------------------------------------
  104.  Version 1.0 Alpha:
  105.  
  106.  InsideMacintoshHelp file provides on-line documentation for the 411 project.
  107.  This version contains all the chapters of InsideMacintosh Volumes I - V.  
  108.  
  109.  
  110. æKY AliasManager
  111. æC 
  112. _______________________________________________________________________________
  113.  
  114. THE ALIAS MANAGER
  115. _______________________________________________________________________________
  116.  
  117. About…the…Alias…Manager…Chapter…Volume…VI
  118. About…the…Alias…Manager…Volume…VI
  119. About…Alias…Records…Volume…VI
  120. Search…Strategies3.…Volume…VI
  121.     Fast…Search
  122.     Exhaustive…Search
  123. Using…the…Alias…Manager…Volume…VI
  124.     Creating…Alias…Records
  125.     Resolving…Alias…Records
  126.         Resolvealias
  127.         Matchalias
  128.     Maintaining…Alias…Records
  129.     Getting…Information…About…Alias…Records
  130.     Customizing…Alias…Records
  131. Alias…Manager…Routines…Volume…VI
  132.     Creating…and…Updating…Alias…Records
  133.     Resolving…and…Reading…Alias…Records
  134.     Filtering…Possible…Targets
  135. Summary…of…the…Alias…Manager…Volume…VI
  136.     Alias…Manager…Constants
  137.     Alias…Manager…Data…Types
  138.     Alias…Manager…Routines…Summary
  139.     Alias…Manager…Application-Defined…Routine
  140.     Alias…Manager…Result…Codes
  141.     Alias…Manager…Assembly-Language…Information
  142. _______________________________________________________________________________
  143.  
  144.  
  145.  
  146. æKY About…the…Alias…Manager…Chapter…Volume…VI
  147. æC »About the Alias Manager Chapter Volume VI                            The Alias Manager
  148. _______________________________________________________________________________
  149.  
  150. This chapter describes how your application can use the Alias Manager to
  151. establish and resolve alias records, which are data structures that describe
  152. file system objects (that is, files, directories, and volumes).
  153.  
  154. You create an alias record to take a fingerprint of a file system object,
  155. usually a file, that you might need to locate again later. You can store the
  156. alias record, instead of a standard file specification, and then let the Alias
  157. Manager find the file again when it’s needed. The Alias Manager contains
  158. algorithms for locating files that have been moved, renamed, copied, or restored
  159. from backup.
  160.  
  161.    Note:  The Alias Manager lets you exploit alias records. It does not directly
  162.  
  163.    manipulate Finder™ aliases, which are created and managed by the user through
  164.    the Finder. The Finder Interface chapter describes Finder aliases and how
  165.    your 
  166.    application can accommodate them.
  167.  
  168. The Alias Manager is available only in system software version 7.0 or later.
  169. Call the Gestalt function, described in the Compatibility Guidelines chapter of
  170. this volume, to determine whether the Alias Manager is present.
  171.  
  172. Read this chapter if you want your application to create and resolve alias
  173. records. You might store an alias record, for example, to identify a customized
  174. dictionary from within a word-processing document. When the user runs a spelling
  175. checker on the document, your application can ask the Alias Manager to resolve
  176. the record to find the correct dictionary.
  177.  
  178. To use this chapter, you should be familiar with the File Manager’s conventions
  179. for identifying files, directories, and volumes, as described in the File
  180. Manager chapter in this volume.
  181.  
  182. _______________________________________________________________________________
  183.  
  184. æKY About…the…Alias…Manager…Volume…VI
  185. æC »About the Alias Manager Volume VI                                    The Alias Manager
  186. _______________________________________________________________________________
  187.  
  188. The Alias Manager creates and resolves alias records. The next section, “About
  189. Alias Records,” describes how you can use alias records.
  190.  
  191. In general, you should use the Alias Manager to create an alias record whenever
  192. you find yourself storing a specific file description, such as filename and
  193. parent directory ID. The Alias Manager stores this information and more in the
  194. alias record, and it also provides a set of search strategies for resolving the
  195. record later. The search strategies are described later in this chapter in
  196. “Resolving Alias Records.”
  197.  
  198. You can use the Alias Manager to
  199.  
  200.    • create alias records
  201.  
  202.    • resolve alias records
  203.  
  204.    • update alias records
  205.  
  206.    • get information about alias records
  207.  
  208. The Alias Manager can track files and directories across volumes. If the target
  209. of an alias record is on an unmounted AppleShare® volume, the Alias Manager
  210. automatically mounts the volume when it resolves the alias. If the target object
  211. is on an unmounted ejectable volume, the Alias Manager prompts the user to
  212. insert the volume.
  213.  
  214. When the Alias Manager creates an alias record, it allocates the storage, fills
  215. in the record, and returns a handle to it. Your application is responsible for
  216. storing the record and retrieving it when needed. Your application must also
  217. supply strategies for handling various alias-resolution problems, described in
  218. “Resolving Alias Records.”
  219.  
  220. To help you understand and use the Alias Manager, this chapter provides
  221.  
  222.    • an overview of alias records
  223.  
  224.    • a description of how the Alias Manager resolves alias records
  225.  
  226.    • specific techniques for using the Alias Manager in your application
  227. _______________________________________________________________________________
  228.  
  229. æKY About…Alias…Records…Volume…VI
  230. æC »About Alias Records Volume VI                                        The Alias Manager
  231. _______________________________________________________________________________
  232.  
  233. An alias record is a data structure that describes a file, directory, or volume.
  234. The record contains
  235.  
  236.    • location information, such as name and parent directory ID
  237.  
  238.    • verification information, such as creation date, file type, and creator
  239.  
  240.    • volume mounting information (that is, server and zone), if applicable
  241.  
  242. By storing alias records, you can allow your users to create a robust connection
  243. to a file—that is, a connection that can survive the moving or renaming of the
  244. target file. The Finder in system software version 7.0, for example, stores
  245. alias records in aliases created by the user to represent other files or
  246. folders. The Edition Manager uses alias records to support data-sharing among
  247. separate documents. (The Finder Interface and Edition Manager chapters in this
  248. volume describe those features in detail.)
  249.  
  250. An alias record is a reliable way to identify a file system object when your
  251. application is communicating with a process that might be running on a different
  252. machine.
  253.  
  254. The creation of an alias record has no effect on the target of the record,
  255. except to establish a file ID if one did not previously exist for the target
  256. file. (See the File Manager chapter of this volume for a description of file
  257. IDs.)
  258.  
  259. The alias record contains only two fields of public information available to
  260. your application. The bulk of the record is managed privately by the Alias
  261. Manager.
  262.  
  263.    TYPE AliasRecord =
  264.         RECORD
  265.            userType:   OSType;   {application’s signature}
  266.            aliasSize:  Integer;  {size of record when created}
  267.            {variable-length private data}
  268.         END;
  269.  
  270. Your application can use the userType field to store its own signature or any
  271. other data that fits into 4 bytes. When the Alias Manager creates an alias
  272. record, it stores 0 in that field.
  273.  
  274. The Alias Manager stores the size of the record when it was created in the
  275. aliasSize field. Knowing the starting size allows you to store and retrieve data
  276. of your own at the end of the record (see “Customizing Alias Records” later in
  277. this chapter). An alias record is typically 200 to 300 bytes long.
  278.  
  279. The private Alias Manager data includes all of the location, verificiation, and
  280. mounting information needed to resolve the alias record with the various search
  281. strategies described in this chapter.
  282.  
  283. When you create an alias record, you have the option of recording a relative
  284. path, that is, the path to the target from another file or directory on the same
  285. volume. (Relative path doesn’t work across volumes.) The beginning point of a
  286. relative path is called the fromFile. To record a relative path, the Alias
  287. Manager saves the distances from the target and the fromFile to their common
  288. parent, that is, the lowest-level directory that appears in the pathnames of
  289. both. The Alias Manager can later use those distances in conjunction with the
  290. full pathname to conduct a relative search.
  291.  
  292. Suppose, for example, that you are writing a word-processing application that
  293. allows the user to build a customized, supplemental dictionary for each
  294. document. You create the dictionary as a separate document in the same directory
  295. as the document it serves, as Figure  27-1 shows.
  296.  
  297. ¿ Figure 27-1   Resolving a relative path ø 
  298.  
  299. When resolving the alias record by using a relative path, the Alias Manager
  300. starts at the directory that is the specified distance above the fromFile, the
  301. directory named Sample in the example in Figure 27-1. The Alias Manager then
  302. constructs a partial pathname by extracting one field of the absolute pathname
  303. for each step from the target to the common parent. In this example, the
  304. distance is one, so the pathname contains only the name of the target document,
  305. Dictionary.
  306.  
  307. In some circumstances, a relative search identifies the correct target when a
  308. direct search cannot. For example, suppose the user of your word-processing
  309. application creates a working copy of a document and dictionary by copying the
  310. entire folder Sample to another disk. The user later updates the original
  311. document and dictionary by copying the folder from the working disk. All of the
  312. underlying file and directory identifications change, but the filenames and
  313. relative path remain the same. When the user later runs the spelling checker on
  314. the document, a relative-path search finds the correct target dictionary.
  315.  
  316. The Alias Manager accepts and returns file specifications in the form of file
  317. system specification records (FSSpec records), described in the File Manager
  318. chapter of this volume. The FSSpec record represents a standard, complete
  319. description of a file system object. It contains a volume reference number, a
  320. parent directory ID, and a name.
  321.  
  322. _______________________________________________________________________________
  323.  
  324. æKY Search…Strategies3.…Volume…VI
  325. æC »Search Strategies3. Volume VI                                        The Alias Manager
  326. _______________________________________________________________________________
  327.  
  328. One of the key features of the Alias Manager is the search strategies built into
  329. the alias-resolution functions. The search strategies are designed to find the
  330. original target of an alias record, even if the target has been moved, renamed,
  331. copied, or restored from backup.
  332.  
  333. The Alias Manager provides two basic alias-resolution algorithms: a fast search
  334. and an exhaustive search. This section describes the search algorithms. For
  335. descriptions of the functions that perform the searches, see “Resolving Alias
  336. Records” and “Resolving and Reading Alias Records” later in this chapter.
  337.  
  338. The first step in any nonrelative search is to identify the volume on which the
  339. target resides. The volume search considers the volume’s name, creation date
  340. (which acts almost as a unique identifier for a volume), and type (for example,
  341. a hard disk, a 3.5-inch floppy disk, or an AppleShare volume).
  342.  
  343. The Alias Manager first looks for a volume that matches all three criteria:
  344. name, creation date, and type. The search succeeds if the volume is mounted and
  345. if its name and creation date have not changed since the record was created. If
  346. the search fails, the Alias Manager attempts to match by creation date and type
  347. only. This step locates volumes that have been renamed. Finally, the Alias
  348. Manager attempts to match by volume name and type only.
  349.  
  350. If the target is on an unmounted AppleShare volume, the Alias Manager attempts
  351. to mount the volume. It presents a name and password dialog if appropriate. If
  352. the target is on an unmounted ejectable volume, the Alias Manager displays a
  353. dialog box prompting the user to insert the volume. Your application can
  354. suppress the automatic mounting, as explained in the description of the
  355. MatchAlias function in “Alias Manager Routines.”
  356. _______________________________________________________________________________
  357.  
  358. æKY Fast…Search
  359. æC »Fast Search                                                          The Alias Manager
  360. _______________________________________________________________________________
  361.  
  362. The fast-search algorithm is designed to find the target of an alias record
  363. quickly.
  364.  
  365. Depending on how you invoke it, the fast-search algorithm starts with either a
  366. relative search (described earlier in “About Alias Records”) or a direct search
  367. (described in this section).  Fast search can perform a relative search whether
  368. or not it has identified the target volume, but it must identify the volume
  369. before it can perform a direct search.
  370.  
  371. In a direct search, the fast-search algorithm first looks for the target by file
  372. ID (if the target is a file) or directory ID (if the target is a directory).
  373. (File IDs and directory IDs are described in the File Manager chapter of this
  374. volume.) Even if a file has been renamed or moved on a volume, the Alias Manager
  375. can find it quickly through its file ID.
  376.  
  377. If the search by file ID or directory ID fails, fast search looks for the target
  378. by name in the original parent directory. This search locates the target if its
  379. file or directory ID has changed but it still exists by the same name in the
  380. parent directory (for example, if the target was restored from backup). Fast
  381. search compares file numbers on files found by name in the correct parent
  382. directory. If the file numbers do not match, the file is treated as a possible
  383. match, that is, it is put on the list of candidates and the search continues. If
  384. the target is not found by name in the parent directory, fast search looks for a
  385. file by file number in the parent directory. A file with the same file number
  386. but a different name replaces a file with the same name but a different file
  387. number in the list of matches.
  388.  
  389. If the search by file ID or directory ID fails and if fast search cannot find
  390. the original parent directory, it searches for the target by full pathname. This
  391. search finds the target if it resides in the same location on the volume but the
  392. directory ID of its parent directory has changed (for example, if the entire
  393. parent directory was restored from backup).
  394.  
  395. If the search by full pathname fails, fast search attempts to find the file by
  396. tracing partial pathnames up through all parent directories, using parent
  397. directory IDs instead of directory names. For example, consider this full
  398. pathname:
  399.  
  400. Loma Prieta:MyReports:October:Sales Report
  401.  
  402. If the search by full pathname fails, fast search first looks for the partial
  403. pathname :Sales Report in the directory with the ID that the directory Loma
  404. Prieta:MyReports:October had when the alias record was created. If that search
  405. fails, it looks for :October:Sales Report in the directory with the ID that Loma
  406. Prieta:MyReports had, and so on.
  407.  
  408. If you did not ask for a search by relative path first but did provide a
  409. starting point for a relative search, and if the alias record contains relative
  410. path information, fast search performs a relative search after the direct
  411. search. The relative search succeeds if the relative path is the same as when
  412. the record was created and if the names of the target and its intervening parent
  413. directories have not changed.
  414.  
  415. _______________________________________________________________________________
  416.  
  417. æKY Exhaustive…Search
  418. æC »Exhaustive Search                                                    The Alias Manager
  419. _______________________________________________________________________________
  420.  
  421. The exhaustive-search algorithm scans an entire volume to look for possible
  422. matches.
  423.  
  424. The Alias Manager typically performs an exhaustive search by calling the File
  425. Manager function PBCatSearch, searching for files or directories with a matching
  426. creation date, creator, and type. (See the File Manager chapter of this volume
  427. for a description of PBCatSearch.)
  428.  
  429. PBCatSearch is available only on HFS volumes, not on MFS volumes. (See the File
  430. Manager chapter of this volume for a description of the two file systems.)
  431. PBCatSearch is also available only on systems running version 7.0 and later.
  432. When PBCatSearch is not available, exhaustive search performs a search of the
  433. entire volume by making a series of indexed File Manager calls, searching for
  434. objects with matching creation date, type, creator, or file number.
  435.  
  436. _______________________________________________________________________________
  437.  
  438. æKY Using…the…Alias…Manager…Volume…VI
  439. æC »Using the Alias Manager Volume VI                                    The Alias Manager
  440. _______________________________________________________________________________
  441.  
  442. You use the Alias Manager primarily to create and resolve alias records. You can
  443. also use it to get information about and update alias records.
  444.  
  445. The Alias Manager creates an alias record in memory and provides you with a
  446. handle to the record. When you no longer need a record in memory, free the
  447. memory by calling the DisposHandle procedure, described in the Memory Manager
  448. chapter of Volume II. You can store and retrieve alias records as resources of
  449. type 'alis'.
  450.  
  451. Alias Manager functions accept and return file specifications in the form of
  452. FSSpec records, which contain a volume reference number, a parent directory ID,
  453. and a target name. See the File Manager chapter in this volume for a description
  454. of file identification conventions.
  455.  
  456. Before calling any of the Alias Manager functions, verify that the Alias Manager
  457. is available by calling the Gestalt function with a selector of
  458. gestaltAliasMgrAttr. If Gestalt sets the gestaltAliasMgrPresent bit in the
  459. response, the Alias Manager is present. For a complete description of the
  460. Gestalt function, see the Compatibility Guidelines chapter of this volume.
  461.  
  462. For more detailed descriptions of the functions described in this section, see
  463. “Alias Manager Routines” later in this chapter.
  464.  
  465. _______________________________________________________________________________
  466.  
  467. æKY Creating…Alias…Records
  468. æC »Creating Alias Records                                               The Alias Manager
  469. _______________________________________________________________________________
  470.  
  471. You create a new alias record by calling one of three functions: NewAlias,
  472. NewAliasMinimal, or NewAliasMinimalFromFullpath. The NewAlias function creates a
  473. complete alias record that can make full use of the alias-resolution algorithms.
  474. The other two functions are streamlined variations designed for circumstances
  475. when speed is more important than robust resolution services. All three
  476. functions allocate the memory for the record, fill it in, and provide a handle
  477. to it.
  478.  
  479. NewAlias always records the name and the file or directory ID of the target, its
  480. creation date, the parent directory name and ID, and the volume name and
  481. creation date. It also records the full pathname of the target and a collection
  482. of other information. You can request that NewAlias store relative path
  483. information as well by supplying a starting point for a relative path (see
  484. “About Alias Records” earlier in this chapter for a description of relative
  485. path).
  486.  
  487. Call NewAlias when you want to create an alias record to store for later use.
  488. For example, suppose you are writing a word-processing application that allows
  489. the user to customize a dictionary for use with a single text file. Your
  490. application stores the custom data in a separate dictionary file in the same
  491. directory as the document. As soon as you create the dictionary file, you call
  492. NewAlias to create an alias record for that file, including path information
  493. relative to the user’s text file:
  494.  
  495. MyErr := NewAlias(textFile, target, myAliasHdl);
  496.  
  497. The textFile parameter is a pointer to a file system specification record that
  498. identifies the starting point for the relative search, in this case the user’s
  499. text file. If you do not want relative path information recorded, pass a value
  500. of NIL in the first parameter.
  501.  
  502. The target parameter is a file system specification record that identifies the
  503. target file, in this example the dictionary file.
  504.  
  505. The myAliasHdl parameter is a variable in which the Alias Manager returns the
  506. handle to the alias record that describes the target.
  507.  
  508. The two variations on the NewAlias function, NewAliasMinimal and
  509. NewAliasMinimalFromFullpath, record only a minimum of information about the
  510. target. NewAliasMinimal records only the target’s name, parent directory ID,
  511. volume name and creation date, and the volume mounting information.
  512. NewAliasMinimalFromFullpath records only the full pathname of the target,
  513. including the volume name.
  514.  
  515. Use NewAliasMinimal or NewAliasMinimalFromFullpath when you are willing to give
  516. up robust alias-resolution service in return for speed. The Finder, for example,
  517. stores minimal aliases in the Apple events that tell your application to open or
  518. print a document. Because the alias record is resolved almost immediately, the
  519. description is likely to remain valid, and the shorter record is probably safe.
  520.  
  521. You can use NewAliasMinimalFromFullpath to create an alias record for a target
  522. that doesn’t exist or that resides on an unmounted volume.
  523.  
  524. _______________________________________________________________________________
  525.  
  526. æKY Resolving…Alias…Records
  527. æC »Resolving Alias Records                                              The Alias Manager
  528. _______________________________________________________________________________
  529.  
  530. The Alias Manager provides two alias-resolution functions:
  531.  
  532.    • the high-level function ResolveAlias, which performs a fast search and 
  533.       identifies only one target
  534.  
  535.    • the low-level function MatchAlias, which can perform a fast search, an 
  536.       exhaustive search, or both, and which can return a list of target
  537.       candidates
  538.  
  539. In general, when you want to identify only the single most likely target of an
  540. alias record, you call ResolveAlias. You call MatchAlias when you want your
  541. program to control the search.
  542.  
  543. This section describes the alias-resolution functions. The section “Search
  544. Strategies for Resolving Alias Records,” earlier in this chapter, describes the
  545. underlying fast and exhaustive searches.
  546.  
  547. _______________________________________________________________________________
  548.  
  549. æKY Resolvealias
  550. æC »Resolvealias                                                         The Alias Manager
  551. _______________________________________________________________________________
  552.  
  553. Typically, you call the ResolveAlias function to resolve an alias record.
  554. ResolveAlias performs a fast search (described earlier in “Strategies for
  555. Resolving Alias Records”) and exits after it identifies one target.
  556.  
  557. By calling low-level functions, ResolveAlias compares some key information about
  558. the identified target with the information stored in the alias record. If any of
  559. the information is different, ResolveAlias automatically updates the record.
  560.  
  561.    Note:  As with all other Alias Manager functions, ResolveAlias updates the 
  562.    record only in memory. Your application is responsible for updating alias
  563.    records 
  564.    stored on disk when appropriate.
  565.  
  566. In the dictionary example, illustrated in Figure  27-1 earlier in the chapter,
  567. the application calls ResolveAlias when the user runs the spelling checker on a
  568. document with a customized dictionary.
  569.  
  570. MyErr := ResolveAlias(textFile, myAliasHdl, target, wasChanged);
  571.  
  572. The textFile parameter is a pointer to a file system specification record that
  573. identifies the starting point for the relative search, in this case the user’s
  574. text file. If you do not want relative path information used in the search, pass
  575. a value of NIL in the first parameter. If you provide a relative starting point,
  576. ResolveAlias performs the relative search first.
  577.  
  578. The myAliasHdl parameter is a handle to the alias record to be resolved. In this
  579. example, the alias record describes the dictionary file.
  580.  
  581. The target parameter is the file system specification record where the Alias
  582. Manager places the results of its search. After ResolveAlias completes, target
  583. contains the specification for the dictionary file.
  584.  
  585. The ResolveAlias function uses the wasChanged parameter to report whether or not
  586. it updated the alias record. After ResolveAlias completes, wasChanged is TRUE if
  587. the record was updated and FALSE if it was not. If you are storing the alias
  588. record, check the value of wasChanged (as well as the function’s result code) to
  589. see whether to update the stored record after resolving an alias.
  590.  
  591. If ResolveAlias can’t resolve the alias record, it returns a non-zero result
  592. code. A result code of fnfErr signals that ResolveAlias has found the correct
  593. volume and parent directory but not the target file or folder. In this case,
  594. ResolveAlias constructs a valid FSSpec record that describes the target. You can
  595. use this record to explore possible solutions to the resolution failure. You
  596. can, for example, use the FSSpec record to create a replacement for a missing
  597. file with the File Manager function FSpCreate.
  598.  
  599. _______________________________________________________________________________
  600.  
  601. æKY Matchalias
  602. æC »Matchalias                                                           The Alias Manager
  603. _______________________________________________________________________________
  604.  
  605. The MatchAlias function is a low-level routine that gives your application
  606. control over the searching algorithm.
  607.  
  608. You can control
  609.  
  610.    • whether to attempt an automatic mounting of unmounted volumes
  611.  
  612.    • whether to search on more than one volume
  613.  
  614.    • whether to perform a fast search, an exhaustive search, or both
  615.  
  616.    • the order of the direct and relative searches in a fast search
  617.  
  618.    • whether to pursue search strategies that require interaction with the user
  619.    (such 
  620.       as asking for a password while mounting an AppleShare volume)
  621.  
  622. You can also specify a maximum number of candidates that MatchAlias can
  623. identify.
  624.  
  625. See “Alias Manager Routines” later in this chapter for details about controlling
  626. a search with the MatchAlias function.
  627.  
  628. You can supply an optional filter function which MatchAlias calls
  629.  
  630.    • each time it identifies a possible match
  631.  
  632.    • when three seconds have elapsed without a match
  633.  
  634. The filter function determines whether or not each candidate is added to the
  635. list of possible targets. It can also terminate the search. See “Filtering
  636. Possible Targets” later in this chapter for a description of the filter
  637. function.
  638.  
  639. MatchAlias returns all candidates that it identifies in an array of file system
  640. specification records.
  641.  
  642. _______________________________________________________________________________
  643.  
  644. æKY Maintaining…Alias…Records
  645. æC »Maintaining Alias Records                                            The Alias Manager
  646. _______________________________________________________________________________
  647.  
  648. You can store alias records as resources of type 'alis'.
  649.  
  650.    CONST  rAliasType = 'alis';
  651.  
  652. To store and retrieve resources, use the standard Resource Manager functions
  653. (AddResource, GetResource, and GetNamedResource) described in the Resource
  654. Manager chapter of Volume I.
  655.  
  656. To update an alias record, use the UpdateAlias function. You typically call
  657. UpdateAlias any time you know that the target of an alias record has been
  658. renamed or otherwise changed.
  659.  
  660. You are most likely to call UpdateAlias after a call to the MatchAlias function.
  661. If MatchAlias identifies a single target, it sets a flag telling you whether or
  662. not the key information about the target file matches the information in the
  663. alias record. It is the responsibility of your application to update the record.
  664.  
  665. The ResolveAlias function automatically updates an alias record if any of the
  666. the key information about the identified target does not match the information
  667. in the record.
  668.  
  669. _______________________________________________________________________________
  670.  
  671. æKY Getting…Information…About…Alias…Records
  672. æC »Getting Information About Alias Records                              The Alias Manager
  673. _______________________________________________________________________________
  674.  
  675. To retrieve information from an alias record without actually resolving the
  676. record, call the GetAliasInfo function. You can use GetAliasInfo to retrieve the
  677. name of the target, the names of the target’s parent directories, the name of
  678. the target’s volume, or, in the case of an AppleShare volume, its zone or server
  679. name.
  680.  
  681. _______________________________________________________________________________
  682.  
  683. æKY Customizing…Alias…Records
  684. æC »Customizing Alias Records                                            The Alias Manager
  685. _______________________________________________________________________________
  686.  
  687. An alias record contains two kinds of information: public information available
  688. to your application and private information available only to the Alias Manager.
  689. Your application can use the first field, userType, to store its own signature
  690. or any other data that fits into 4 bytes. Your application can use the second
  691. field, aliasSize, to customize the alias record for storing additional data.
  692.  
  693. The Alias Manager stores the size of the record when it is created or updated in
  694. the aliasSize field. To customize an alias record, you first increase the size
  695. of the record with the SetHandleSize procedure, described in the Memory Manager
  696. chapter of Volume II. You can then find the starting address of your own data in
  697. the record by adding the record’s starting address to the length recorded in the
  698. aliasSize field. If you expand the record through the Memory Manager, the Alias
  699. Manager preserves your data, even if it changes the size of its own data when
  700. updating the record.
  701.  
  702. In general, you should customize only alias records that you have created.
  703.  
  704. _______________________________________________________________________________
  705.  
  706. æKY Alias…Manager…Routines…Volume…VI
  707. æC »Alias Manager Routines Volume VI                                     The Alias Manager
  708. _______________________________________________________________________________
  709.  
  710. This section describes the routines you use to create, update, resolve, and read
  711. alias records.
  712.  
  713. Alias Manager routines use file system specification records (FSSpec records) to
  714. identify files, directories, and volumes. To create a FSSpec record, call the
  715. function MakeFSSpec, described in the File Manager chapter of this volume.
  716.  
  717. The Alias Manager routines can return the result codes listed in this section or
  718. any other applicable file-system or memory-management result codes.
  719.  
  720.  
  721.  
  722.  
  723.  
  724.  
  725.  
  726. _______________________________________________________________________________
  727.  
  728. æKY Creating…and…Updating…Alias…Records
  729. æC »Creating and Updating Alias Records                                  The Alias Manager
  730. _______________________________________________________________________________
  731.  
  732. You use the NewAlias function to create a complete alias record.
  733.  
  734. FUNCTION NewAlias (fromFile: FSSpecPtr; target: FSSpec;
  735.                    VAR alias: AliasHandle) : OSErr;
  736.  
  737. NewAlias creates an alias record that describes the specified target. It
  738. allocates the storage, fills in the record, and puts a record handle in the
  739. alias parameter. NewAlias always records the name and file or directory ID of
  740. the target, its creation date, the parent directory name and ID, and the volume
  741. name and creation date. It also records the full pathname of the target and a
  742. collection of other information relevant to locating the target, verifying the
  743. target, and mounting the target’s volume, if necessary. You can request that it
  744. store relative path information as well by supplying a starting point for a
  745. relative path (see “About Alias Records” for a description of relative path).
  746.  
  747. The fromFile parameter represents the starting point for a relative path, to be
  748. used later in a relative search. If you do not need relative path information in
  749. the record, pass a fromFile value of NIL. If you want NewAlias to record
  750. relative path information, pass a pointer to a valid FSSpec record in this
  751. parameter. The two files or directories, fromFile and target, must reside on the
  752. same volume.
  753.  
  754. The target parameter is a FSSpec record for the target of the alias record.
  755.  
  756. NewAlias puts a handle to the newly created alias record in the alias parameter.
  757. If the function fails to create an alias record, it sets alias to NIL.
  758.  
  759. You use the NewAliasMinimal function to create a short alias record quickly.
  760.  
  761. FUNCTION NewAliasMinimal (target: FSSpec; VAR alias: AliasHandle) : 
  762.                           OSErr;
  763.  
  764. NewAliasMinimal creates an alias record that contains only the minimum
  765. information necessary to describe the target: the target name, the parent
  766. directory ID, the volume name and creation date, and the volume mounting
  767. information. NewAliasMinimal uses the standard alias record data structure, but
  768. fills in only parts of the record.
  769.  
  770. The target parameter points to a FSSpec record for the target of the alias
  771. record.
  772.  
  773. NewAliasMinimal puts a handle to the newly created alias record in the alias
  774. parameter. If the function fails to create an alias record, it sets alias to
  775. NIL.
  776.  
  777. The ResolveAlias function, described in “Resolving and Reading Alias Records”
  778. later in this chapter, never updates a minimal alias record.
  779.  
  780. You use the function NewAliasMinimalFromFullpath to quickly create an alias
  781. record that contains only the full pathname of the target.
  782.  
  783. FUNCTION NewAliasMinimalFromFullpath (fullpathLength: Integer;
  784.                                       fullpath: Ptr; zoneName: Str32; 
  785.                                       serverName: Str31;
  786.                                       VAR alias: AliasHandle) : OSErr;
  787.  
  788. NewAliasMinimalFromFullpath creates an alias record that identifies the target
  789. by full pathname. You can call NewAliasMinimalFromFullpath to create an alias
  790. record for a file that doesn’t exist or that resides on an unmounted volume.
  791. NewAliasMinimalFromFullpath uses the standard alias record data structure, but
  792. it fills in only the information provided in the input parameters. You can
  793. therefore use NewAliasMinimalFromFullpath to create alias records for targets on
  794. unmounted volumes.
  795.  
  796. The fullpathLength parameter identifies the number of characters in the full
  797. pathname.
  798.  
  799. The fullpath parameter is a pointer to a buffer that contains the full pathname
  800. of the target. The full pathname starts with the name of the volume, includes
  801. all of the directory names in the path to the target, and ends with the target
  802. name. (For a description of pathnames, see the File Manager chapter in this
  803. volume.)
  804. The parameters zoneName and serverName are strings that identify the AppleTalk
  805. zone and server name of the AppleShare volume on which the target resides. Set
  806. these parameters to null strings if you do not need them.
  807.  
  808. NewAliasMinimalFromFullpath puts a handle to the newly created alias record in
  809. the alias parameter. If the function fails to create an alias record, it sets
  810. alias to NIL.
  811.  
  812. You use the UpdateAlias function to update an alias record.
  813.  
  814. FUNCTION UpdateAlias (fromFile: FSSpecPtr; target: FSSpec;
  815.                       alias: AliasHandle; VAR wasChanged: Boolean) : 
  816.                       OSErr;
  817.  
  818. UpdateAlias updates the alias record pointed to by the alias parameter so that
  819. it describes the target specified by the target parameter. UpdateAlias rebuilds
  820. the entire alias record, filling it in as the NewAlias function would.
  821.  
  822. The fromFile parameter represents the starting point for a relative path, to be
  823. used later in a relative search. If you do not need relative path information in
  824. the record, pass a fromFile value of NIL. If you want UpdateAlias to record
  825. relative path information, pass a pointer to a valid FSSpec record in this
  826. parameter. The two files or directories, fromFile and target, must reside on the
  827. same volume.
  828.  
  829. The target parameter is the target of the alias record. This parameter must be a
  830. valid FSSpec record.
  831.  
  832. The alias parameter is a handle to the alias record to be updated.
  833.  
  834. If the newly constructed alias record is exactly the same as the old one,
  835. UpdateAlias sets the wasChanged parameter to FALSE. Otherwise, it sets it to
  836. TRUE. Check this parameter to determine whether you need to save an updated
  837. record.
  838.  
  839. UpdateAlias always creates a complete alias record. When you update a minimal
  840. alias record with UpdateAlias, you convert the minimal record to a complete
  841. record.
  842.  
  843.    Result codes
  844.    paramErr         –50         target, alias, or both are NIL, or the alias
  845.    record is corrupt
  846. _______________________________________________________________________________
  847.  
  848. æKY Resolving…and…Reading…Alias…Records
  849. æC »Resolving and Reading Alias Records                                  The Alias Manager
  850. _______________________________________________________________________________
  851.  
  852. You use the ResolveAlias function to identify the single most likely target of
  853. an alias record. 
  854.  
  855. FUNCTION ResolveAlias (fromFile: FSSpecPtr; alias: AliasHandle;
  856.                        VAR target: FSSpec; VAR wasChanged: Boolean) : 
  857.                        OSErr;
  858.  
  859. ResolveAlias performs a fast search for the target of the alias, as described
  860. earlier in “Search Strategies for Resolving Alias Records.” If the resolution is
  861. successful, ResolveAlias returns the FSSpec record for the target file system
  862. object through the target parameter, updates the alias record if necessary, and
  863. reports whether or not the record was updated through the wasChanged parameter.
  864. If the target is on an unmounted AppleShare volume, ResolveAlias automatically
  865. mounts the volume. If the target is on an unmounted ejectable volume,
  866. ResolveAlias asks the user to insert the volume. ResolveAlias exits after it
  867. finds one acceptable target.
  868.  
  869. The fromFile parameter represents the starting point for a relative search. If
  870. you pass a fromFile parameter of NIL, ResolveAlias performs only a direct
  871. search. If you pass a pointer to a valid FSSpec record in the fromFile
  872. parameter, ResolveAlias performs a relative search for the target, followed by a
  873. direct search only if the relative search fails. If you want to perform a direct
  874. search followed by a relative search, you must use the MatchAlias function.
  875.  
  876. The alias parameter is a handle to the alias record to be resolved and, if
  877. necessary, updated.
  878.  
  879. The target parameter receives the FSSpec record of the target file system
  880. object.
  881.  
  882. After it identifies a target, ResolveAlias compares some key information about
  883. the target with the information in the alias record. (The upcoming description
  884. of the MatchAlias function lists the key information.) If the information is
  885. different, ResolveAlias updates the record to match the target. If it updates
  886. the alias record, ResolveAlias sets the wasChanged parameter to TRUE. Otherwise,
  887. it sets it to FALSE. (Because ResolveAlias never updates a minimal alias, it
  888. never sets wasChanged to TRUE when resolving a minimal alias.)
  889.  
  890. When it finds the specified volume and parent directory but fails to find the
  891. target file or directory in that location, ResolveAlias returns a result code of
  892. fnfErr and fills in the target parameter with a complete FSSpec record
  893. describing the target (that is, the volume reference number, parent directory
  894. ID, and file or folder name). The FSSpec record is valid, although the object it
  895. describes does not exist. This information is intended as a “hint” that lets you
  896. explore possible solutions to the resolution failure. You can, for example, use
  897. the FSSpec record to create a replacement for a missing file with the File
  898. Manager function FSpCreate.
  899.  
  900. ResolveAlias displays the standard dialog boxes when it needs input from the
  901. user, such as a name and password for mounting a remote volume. The user can
  902. cancel the resolution through these dialog boxes.
  903.  
  904.       Result codes
  905.              dirNFErr                –120         Parent directory not found
  906.              fnfErr                        –43         Target not found, but
  907.              volume and parent 
  908.                                                                directory found;
  909.                                                                target parameter
  910.                                                                contains a 
  911.                                                                valid FSSpec
  912.                                                                record
  913.              nsvErr                       –35        Volume not found
  914.              paramErr                  –50        The alias parameter is NIL, or
  915.              the alias record is 
  916.                                                                corrupt
  917.              usrCanceledErr     –128         The user cancelled
  918.  
  919. You use the MatchAlias function to identify a list of possible matches and pass
  920. the list through an optional selection filter. The filter can pass more than one
  921. possible match.
  922.  
  923. FUNCTION MatchAlias (fromFile: FSSpecPtr; rulesMask: LongInt;
  924.                      alias: AliasHandle; VAR aliasCount: Integer; 
  925.                      aliasList: FSSpecArrayPtr; VAR needsUpdate: Boolean;
  926.                      aliasFilterProcPtr: ProcPtr; yourDataPtr: UNIV Ptr) 
  927.                      : OSErr;
  928.  
  929. MatchAlias resolves the alias record specified by the alias parameter, following
  930. the rules specified by the rulesMask parameter, and returns a list of possible
  931. candidates in the structure specified by the aliasList parameter. MatchAlias
  932. places the number of candidates identified in the aliasCount parameter.
  933.  
  934. The fromFile parameter represents the starting point for a relative search. If
  935. you do not want MatchAlias to perform a relative search, set fromFile to NIL. If
  936. you want MatchAlias to perform a relative search, pass a pointer to a file
  937. system specification record that describes the starting point for the search.
  938.  
  939. The rulesMask parameter specifies a set of rules to guide the resolution. Pass
  940. the sum of all of the rules you want to invoke.
  941.  
  942.    Constant                        Description
  943.  
  944.    kARMsearch                 Perform a fast search for the alias target.
  945.  
  946.                                              If kARMsearchRelFirst is not set,
  947.                                              perform a direct search 
  948.                                              first, followed by a relative
  949.                                              search only if the fromFile 
  950.                                              parameter is not NIL and the list
  951.                                              of matches is not full.
  952.  
  953.    kARMsearchMore        Perform an exhaustive search for the alias target.
  954.  
  955.                                               On HFS volumes, the exhaustive
  956.                                               search uses the File 
  957.                                               Manager function PBCatSearch to
  958.                                               identify candidates with
  959.                                               matching creation date, type, and
  960.                                               creator. PBCatSearch is 
  961.                                               available only on HFS volumes and
  962.                                               only on systems 
  963.                                               running version 7.0 or later. On
  964.                                               MFS volumes or HFS 
  965.                                               volumes that do not support
  966.                                               PBCatSearch the exhaustive 
  967.                                               search makes a series of indexed
  968.                                               calls to File Manager 
  969.                                               functions, using the same search
  970.                                               criteria.
  971.  
  972.                                                If you set kARMsearchMore and one
  973.                                                or both of 
  974.                                                kARMsearch and
  975.                                                kARMsearchRelFirst, MatchAlias 
  976.                                                performs the fast search first.
  977.  
  978.    kARMsearchRelFirst     If kARMsearch is also set, perform a relative search
  979.    before
  980.                                                the direct search. (If kARMsearch
  981.                                                is also set and the target 
  982.                                                is found through the direct
  983.                                                search, MatchAlias sets the 
  984.                                                needsUpdate flag to TRUE.)
  985.  
  986.                                                If neither kARMsearch nor
  987.                                                kARMsearchMore is set, 
  988.                                                perform only a relative search.
  989.  
  990.                                                If kARMsearch is not set but
  991.                                                kARMsearchMore is set, 
  992.                                                perform a relative search
  993.                                                followed by an exhaustive 
  994.                                                search.
  995.  
  996.    kARMmountVol           Automatically try to mount the target’s volume if it
  997.    is not
  998.                                                mounted.
  999.  
  1000.    kARMmultVols             Search all mounted volumes.
  1001.  
  1002.                                                The search begins with the volume
  1003.                                                on which the target 
  1004.                                                resided when the record was
  1005.                                                created.
  1006.  
  1007.                                                When you specify a fast search of
  1008.                                                all mounted volumes, 
  1009.                                                MatchAlias performs a formal fast
  1010.                                                search only on the 
  1011.                                                volume described in the alias
  1012.                                                record. On all other 
  1013.                                                volumes, it looks for the target
  1014.                                                by ID or by name in the 
  1015.                                                directory with the specified
  1016.                                                parent directory ID.
  1017.  
  1018.                                               When you specify an exhaustive
  1019.                                               search of multiple 
  1020.                                                volumes, MatchAlias performs the
  1021.                                                same search on all 
  1022.                                                volumes.
  1023.  
  1024.                                               When resolving an alias record
  1025.                                               created by  
  1026.                                               NewAliasMinimalFromFullpath,
  1027.                                               MatchAlias ignores this
  1028.                                               flag.
  1029.  
  1030.    kARMnoUI                    Stop if a search requires user interaction, such
  1031.    as a 
  1032.                                              password dialog box when mounting a
  1033.                                              remote volume.
  1034.  
  1035.                                              If user interaction is needed and
  1036.                                              kARMnoUI is in effect, 
  1037.                                              the search fails.
  1038.  
  1039. You must specify at least one of the first three parameters: kARMsearch,
  1040. kARMsearchMore, and kARMsearchRelFirst.
  1041.  
  1042. The alias parameter is a handle to the alias record to be resolved.
  1043.  
  1044. Your application can specify a maximum number of possible matches by setting the
  1045. aliasCount parameter. MatchAlias changes the aliasCount parameter to the actual
  1046. number of candidates identified. If MatchAlias finds the parent directory on the
  1047. correct volume but does not find the target, it sets the aliasCount parameter to
  1048. 1, puts the file system specification record for the target in the results list,
  1049. and returns fnfErr. The FSSpec record is valid, although the object it describes
  1050. does not exist. This information is intended as a “hint” that lets you explore
  1051. possible solutions to the resolution failure. You can, for example, use the
  1052. FSSpec record to create a replacement for a missing file with the File Manager
  1053. function FSpCreate.
  1054.  
  1055. The aliasList parameter points to the array that holds the results of the
  1056. search.
  1057.  
  1058. The needsUpdate flag is a signal to your application that the record might need
  1059. to be updated. After it identifies a target, MatchAlias compares some key
  1060. information about the target with the same information in the record. If the
  1061. information does not match, MatchAlias sets the needsUpdate flag to TRUE. The
  1062. key information is
  1063.  
  1064.    • the name of the target
  1065.  
  1066.    • the directory ID of the target’s parent
  1067.  
  1068.    • the file ID or directory ID of the target
  1069.  
  1070.    • the name and creation date of the volume on which the target resides
  1071.  
  1072. MatchAlias also sets the needsUpdate flag to TRUE if it identifies a list of
  1073. possible matches rather than a single match or if kARMsearchRelFirst is set but
  1074. the target is identified through either a direct search or an exhaustive search.
  1075. Otherwise, MatchAlias sets the needsUpdate flag to FALSE. MatchAlias always sets
  1076. the needsUpdate flag to FALSE when resolving an alias created by
  1077. NewAliasMinimal. If you want to update the alias record to reflect the final
  1078. results of the resolution, call UpdateAlias.
  1079.  
  1080. The aliasFilter parameter points to a filter function supplied by your
  1081. application. The Alias Manager executes this function each time it identifies a
  1082. possible match and after the search has continued for three seconds without  a
  1083. match. Your filter function returns a Boolean value that determines whether the
  1084. possible match is discarded (TRUE) or added to the list of possible targets
  1085. (FALSE). It can also terminate the search by setting the variable parameter
  1086. quitFlag. See “Filtering Possible Targets” later in the chapter for a
  1087. description of the filter function, which follows this syntax:
  1088.  
  1089.    FUNCTION MyMatchAliasFilter (cpbPtr: CInfoPBPtr;
  1090.                               VAR quitFlag: Boolean;
  1091.                               myDataPtr: Ptr): Boolean;
  1092.  
  1093. The yourDataPtr parameter can point to any data that your application might need
  1094. in the filter function. Use the myDataPtr parameter to pass global or local data
  1095. to your filter function.
  1096.  
  1097.    Result codes
  1098.           nsvErr                    –35        The volume is not mounted
  1099.           fnfErr                      –43         No target was found
  1100.           paramErr                –50        target, alias, or both are NIL, or
  1101.           the alias record is
  1102.                                                           corrupt
  1103.           usrCanceledErr    –128       The user cancelled the operation
  1104.  
  1105. You can use the GetAliasInfo function to get information from an alias record
  1106. without actually resolving the record.
  1107.  
  1108. FUNCTION GetAliasInfo (alias: AliasHandle; index: AliasInfoType;
  1109.                        VAR theString: Str63 ) : OSErr;
  1110.  
  1111. GetAliasInfo retrieves the information specified by the index parameter from the
  1112. record pointed to by the alias parameter and places it in the parameter
  1113. theString.
  1114.  
  1115. The alias parameter is a handle to the alias record to be read.
  1116.  
  1117. The index parameter specifies the kind of information to be retrieved. If index
  1118. is a positive integer, GetAliasInfo retrieves the parent directory that has the
  1119. same hierarchical level above the target as the index parameter (for example, an
  1120. index value of 2 returns the name of the parent directory of the target’s parent
  1121. directory). You can therefore assemble the names of the target and all of its
  1122. parent directories by making repeated calls to GetAliasInfo with incrementing
  1123. index values, starting with a value of 0. When index is greater than the number
  1124. of levels between the target and the root, GetAliasInfo returns an empty string.
  1125. You can also set the index parameter to one of these values:
  1126.  
  1127.    Constant               Value        Description
  1128.  
  1129.    asiZoneName         –3            If the record represents a target on an
  1130.    AppleShare 
  1131.                                                       volume, retrieve the
  1132.                                                       server’s zone name.
  1133.                                                       Otherwise, 
  1134.                                                       return an empty string.
  1135.  
  1136.    asiServerName       –2            If the record represents a target on an
  1137.    AppleShare 
  1138.                                                        volume, retrieve the
  1139.                                                        server name. Otherwise,
  1140.                                                        return
  1141.                                                        an empty string.
  1142.  
  1143.    asiVolumeName    –1            Return the name of the volume on which the
  1144.    target 
  1145.                                                         resides.
  1146.  
  1147.    asiAliasName            0            Return the name of the target.
  1148.  
  1149.    asiParentName          1            Return the name of the parent directory
  1150.    of the target 
  1151.                                                        of the record. If the
  1152.                                                        target is a volume,
  1153.                                                        return the 
  1154.                                                        volume name.
  1155.  
  1156. GetAliasInfo places the requested information in the parameter theString.
  1157.  
  1158. GetAliasInfo returns the information stored in the alias record, which might not
  1159. be current. To ensure that the information is current, you can resolve and
  1160. update the alias record before calling GetAliasInfo.
  1161.  
  1162. GetAliasInfo cannot provide all kinds of information on a minimal alias.
  1163.  
  1164.    Result codes
  1165.           paramErr         –50               alias, theString, or both are NIL;
  1166.           the index is less
  1167.                                                           than asiZoneName; or
  1168.                                                           the alias record is
  1169.                                                           corrupt
  1170. _______________________________________________________________________________
  1171.  
  1172. æKY Filtering…Possible…Targets
  1173. æC »Filtering Possible Targets                                           The Alias Manager
  1174. _______________________________________________________________________________
  1175.  
  1176. You can write your own filter function to examine possible targets identified by
  1177. the MatchAlias function. MatchAlias calls your filter function each time it
  1178. identifies a possible match and when three seconds have elapsed without a match.
  1179.  
  1180. The filter function takes three parameters and returns a Boolean value:
  1181.  
  1182. FUNCTION MyMatchAliasFilter (cpbPtr: CInfoPBPtr; VAR quitFlag: Boolean;    
  1183.                              myDataPtr: Ptr): Boolean;
  1184.  
  1185. The cpbPtr parameter points to the catalog information parameter block record
  1186. (as returned by the File Manager function PBGetCatInfo) of the possible match.
  1187. MatchAlias sets this parameter to NIL if it is calling your function to give it
  1188. the periodic chance to terminate the search. (Do not use this pointer without
  1189. checking for NIL.)
  1190.  
  1191. Your filter function sets the quitFlag parameter to terminate the search.
  1192.  
  1193. The myDataPtr parameter points to any customized data that your application
  1194. passed when it called MatchAlias. This parameter allows your filter function to
  1195. access any data that your application has set up on its own.
  1196.  
  1197. The Boolean return value determines whether the possible match is discarded
  1198. (TRUE) or added to the list of possible targets (FALSE).
  1199.  
  1200. _______________________________________________________________________________
  1201.  
  1202. æKY Summary…of…the…Alias…Manager…Volume…VI
  1203. æC »Summary of the Alias Manager Volume VI                               The Alias Manager
  1204. _______________________________________________________________________________
  1205.  
  1206. Click the arrow in the lower-right corner of this wondow to see the summary
  1207. sections of the constants, data types, and routines for the Alias Manager.
  1208. _______________________________________________________________________________
  1209.  
  1210. æKY Alias…Manager…Constants
  1211. æC »Alias Manager Constants                                              The Alias Manager
  1212. _______________________________________________________________________________
  1213.  
  1214. CONST
  1215.      rAliasType          =  'alis';  {alias record resource type}
  1216.  
  1217.      {rulesMask for MatchAlias}
  1218.      kARMmountVol        =  $0001;   {mount the volume automatically}
  1219.      kARMnoUI            =  $0002;   {suppress user interface}
  1220.      kARMmultVols        =  $0008;   {search on multiple volumes}
  1221.      kARMsearch          =  $0100;   {perform a fast search}
  1222.      kARMsearchMore      =  $0200;   {perform an exhaustive search}
  1223.      kARMsearchRelFirst  =  $0400;   {perform a relative search first}
  1224.  
  1225.      {index values for GetAliasInfo}
  1226.      asiZoneName         =     –3;   {get zone name}
  1227.      asiServerName       =     –2;   {get server name}
  1228.      asiVolumeName       =     –1;   {get volume name}
  1229.      asiAliasName        =      0;   {get target name}
  1230.      asiParentName       =      1;   {get parent directory name}
  1231. _______________________________________________________________________________
  1232.  
  1233. æKY Alias…Manager…Data…Types
  1234. æC »Alias Manager Data Types                                             The Alias Manager
  1235. _______________________________________________________________________________
  1236.  
  1237. TYPE  AliasHandle    =                ^AliasPtr;
  1238.       AliasPtr       =                ^AliasRecord;
  1239.  
  1240.       AliasRecord    =
  1241.       RECORD
  1242.          userType:   OSType;           {application’s signature}
  1243.          aliasSize:  Integer;          {size of record when created}
  1244.          {variable-length private data}
  1245.       END;
  1246.   
  1247.       AliasInfoType  =  Integer;       {alias record information type}
  1248.   
  1249.       AliasFilterProcPtr  =  ProcPtr;  {application-defined routine; }
  1250.                                        { see sample }
  1251.                                        { FUNCTION MyMatchAliasFilter}
  1252. _______________________________________________________________________________
  1253.  
  1254. æKY Alias…Manager…Routines…Summary
  1255. æC »Alias Manager Routines Summary                                       The Alias Manager
  1256. _______________________________________________________________________________
  1257.  
  1258. Creating and Updating Alias Records
  1259.  
  1260. FUNCTION NewAlias                     (fromFile: FSSpecPtr;
  1261.                                        target: FSSpec;
  1262.                                        VAR alias: AliasHandle) : OSErr;
  1263. FUNCTION NewAliasMinimal              (target: FSSpec;
  1264.                                        VAR alias: AliasHandle) : OSErr;
  1265. FUNCTION NewAliasMinimalFromFullpath  (fullpathLength: Integer;
  1266.                                        fullpath: Ptr; zoneName: Str32; 
  1267.                                        serverName: Str31;
  1268.                                        VAR alias: AliasHandle) : OSErr;
  1269. FUNCTION UpdateAlias                  (fromFile: FSSpecPtr;
  1270.                                        target: FSSpec; alias: AliasHandle; 
  1271.                                        VAR wasChanged: Boolean) : OSErr;
  1272.  
  1273.  
  1274. Resolving and Reading Alias Records
  1275.  
  1276. FUNCTION ResolveAlias                  (fromFile: FSSpecPtr;
  1277.                                         alias: AliasHandle;
  1278.                                         VAR target: FSSpec;
  1279.                                         VAR wasChanged: Boolean) : OSErr;
  1280.  
  1281. FUNCTION MatchAlias                    (fromFile: FSSpecPtr;
  1282.                                         rulesMask: LongInt;
  1283.                                         alias: AliasHandle;
  1284.                                         VAR aliasCount: Integer;
  1285.                                         aliasList: FSSpecArrayPtr;
  1286.                                         VAR needsUpdate: Boolean; 
  1287.                                         aliasFilterProcPtr: ProcPtr; 
  1288.                                         yourDataPtr: UNIV Ptr) : OSErr;
  1289.  
  1290. FUNCTION GetAliasInfo                  (alias: AliasHandle;
  1291.                                         index: AliasInfoType;
  1292.                                         VAR theString: Str63) : OSErr;
  1293. _______________________________________________________________________________
  1294.  
  1295. æKY Alias…Manager…Application-Defined…Routine
  1296. æC »Alias Manager Application-Defined Routine                            The Alias Manager
  1297. _______________________________________________________________________________
  1298.  
  1299. FUNCTION MyMatchAliasFilter                (cpbPtr: CInfoPBPtr;
  1300.                                             VAR quitFlag: Boolean;
  1301.                                             myDataPtr: Ptr): Boolean;
  1302. _______________________________________________________________________________
  1303.  
  1304. æKY Alias…Manager…Result…Codes
  1305. æC »Alias Manager Result Codes                                           The Alias Manager
  1306. _______________________________________________________________________________
  1307.  
  1308. nsvErr                       –35       The volume is not mounted
  1309. fnfErr                         –43       No target was found
  1310. paramErr                  –50       One or more parameters are NIL, or a handle
  1311. is corrupt
  1312. dirNFErr                –120       Parent directory not found
  1313. usrCanceledErr     –128       The user cancelled the operation
  1314. _______________________________________________________________________________
  1315.  
  1316. æKY Alias…Manager…Assembly-Language…Information
  1317. æC »Alias Manager Assembly-Language Information                          The Alias Manager
  1318. _______________________________________________________________________________
  1319.  
  1320. Alias Record Data Structure
  1321.  
  1322. userType            4 bytes            file type of target file
  1323. aliasSize             2 bytes            size of record in bytes
  1324. {variable-length private data}
  1325.  
  1326.  
  1327.  
  1328.  
  1329. _______________________________________________________________________________
  1330.  
  1331.  
  1332. æKY AppleDesktopBus
  1333. æC 
  1334. THE APPLE DESKTOP BUS
  1335. _______________________________________________________________________________
  1336.  
  1337. About…The…AppleDesktopBus…Chapter
  1338. About…the…Apple…Desktop…Bus
  1339. ADB…Manager…Routines
  1340. Writing…ADB…Device…Drivers
  1341. Summary…of…the…ADB
  1342. _______________________________________________________________________________
  1343.  
  1344.  
  1345.  
  1346. æKY About…The…AppleDesktopBus…Chapter
  1347. æC »ABOUT THIS CHAPTER                                        AppleDesktopBus
  1348. _______________________________________________________________________________
  1349.  
  1350. This chapter tells you how to accomplish low-level communication with peripheral
  1351. devices that are connected to the Apple Desktop Bus (ADB).
  1352.  
  1353. Reader’s guide:    The standard mouse and keyboard drivers automatically take
  1354.                    care of all required ADB access functions. When the user
  1355.                    manipulates the mouse or keyboard, the system calls the
  1356.                    appropriate driver and the application never uses the ADB
  1357.                    Manager. Hence you need the information in this chapter only
  1358.                    if you are writing a special driver, such as a driver for a
  1359.                    new user-input device.
  1360.  
  1361. The ADB is a simple local-area network that connects low-speed input-only devices to
  1362. the operating system. In the Macintosh II and Macintosh SE computers, the ADB is used
  1363. to communicate with one or more keyboards, the mouse, and other user input devices.
  1364.  
  1365. Keys located on multiple keyboards are distinguished by the keyboard event message,
  1366. as described in the Toolbox Event Manager chapter.
  1367.  
  1368. Note:  An ADB, using the same operating protocols, is also part of the
  1369.        Apple IIgs computer.
  1370.  
  1371. This chapter contains three principal sections:
  1372.  
  1373.   •  a description of the Apple Desktop Bus and how it works
  1374.   •  a description of the ADB Manager. This section of system ROM contains
  1375.      the routines that a driver must use to access devices connected to the ADB.
  1376.   •  a discussion of the special requirements for drivers that support
  1377.      devices connected to the ADB
  1378.  
  1379. You should already be familiar with
  1380.  
  1381.   •  the hardware interface to the Apple Desktop Bus, described in the
  1382.      Macintosh Family Hardware Reference
  1383.   •  events generated by ADB keyboard devices (described in the Toolbox
  1384.      Event Manager chapter) if your driver communicates with one or more
  1385.      keyboards
  1386.  
  1387. _______________________________________________________________________________
  1388.  
  1389.  
  1390. æKY About…the…Apple…Desktop…Bus
  1391. æC »ABOUT THE APPLE DESKTOP BUS                               AppleDesktopBus
  1392. _______________________________________________________________________________
  1393.  
  1394. The Apple Desktop Bus connects up to 16 low-speed input-only devices to the Macintosh
  1395. II or Macintosh SE computer. Each device can maintain up to four variable-size registers,
  1396. whose contents can be read from or written to by the ADB network. Each register may
  1397. contain from two to eight bytes. Two of the device registers have an assigned meaning
  1398. and a standardized format: register 0, used for interrupt information, and register
  1399. 3, containing the device’s identification number. The other two device registers have
  1400. no assigned meaning, and may have different meanings for read and write operations.
  1401.  
  1402. The system communicates with the Apple Desktop Bus through the system’s Versatile
  1403. Interface Adapter chip (VIA). The VIA is described in the Macintosh Hardware chapter.
  1404.  
  1405. Warning:  The ADB does not support connecting a device while the computer
  1406.           is running. The result may be to reinitialize all devices on the
  1407.           bus without informing the system.
  1408.  
  1409. The system always controls the bus. It issues commands to specific devices on the bus
  1410. and they respond by accepting data, sending data, or changing their configuration.
  1411. These commands are discussed below.
  1412.  
  1413. Note:  Devices connected to the ADB contain their own single-chip
  1414.        microprocessors, which handle both device routines and the
  1415.        ADB interface. If the system sends commands to a device with
  1416.        a duty cycle of more than 50%, the device’s microprocessor
  1417.        may become overloaded.
  1418.  
  1419. _______________________________________________________________________________
  1420.  
  1421. »Bus Commands
  1422.  
  1423. Each bus command consists of a byte that the system sends to a device connected to
  1424. the ADB. Applications may place bus commands on the network by calling the routine
  1425. ADBOp, discussed under “ADB Manager Routines” later in this chapter. There are four
  1426. bus commands; their bit layouts are shown in Figure 1.  All other bit layouts are
  1427. reserved.
  1428.  
  1429. •••Refer to Figure 1.•••
  1430.  
  1431. Figure 1–ADB Command Formats
  1432.  
  1433. The individual commands are discussed below.
  1434.  
  1435. Warning:  Values of the low bytes of the ADB command formats other than
  1436.           those shown in Figure 1 are reserved, and should not be used.
  1437.  
  1438. »SendReset
  1439.  
  1440. The SendReset command forces a hardware reset of all devices connected to the ADB.
  1441. Such a reset clears all pending device actions and places the devices in their startup
  1442. state. All devices are able to accept new ADB commands and user inputs immediately
  1443. thereafter. All devices ignore the high-order four bits of the SendReset command.
  1444.  
  1445. »Flush
  1446.  
  1447. The Flush command flushes data from the single device specified by the network address
  1448. in its high-order four bits. Network  addresses are discussed below, under “Device
  1449. Addressing”. It purges any pending user inputs and make the device ready to accept
  1450. new commands and input data.
  1451.  
  1452. »Listen
  1453.  
  1454. The Listen command is used to send instructions to devices connected to the ADB. It
  1455. transfers data from a buffer in system RAM to a register in the device specified by
  1456. the network address in its high-order four bits. The device register is specified by
  1457. the low-order two bits of the Listen command.
  1458.  
  1459. »Talk
  1460.  
  1461. The Talk command is used to fetch user inputs from devices connected to the ADB. It
  1462. is the complement of the Listen command. It transfers data from a register in the
  1463. device specified by the network address in its high-order four bits to a buffer in
  1464. system RAM. The device register is specified by the low-order two bits of the Talk
  1465. command.
  1466.  
  1467. _______________________________________________________________________________
  1468.  
  1469. »Device Registers
  1470.  
  1471. Each device connected to the ADB contains four registers, each of which may store
  1472. from two to eight bytes of data. Each register is identified by the value of the
  1473. low-order two bits in a Listen or Talk command. Registers 0 and 3 have dedicated
  1474. functions; registers 1 and 2 are used for purposes specific to each device, and need
  1475. not be present in a device.
  1476.  
  1477. Note:  ADB device registers are virtual registers; they need not be
  1478.        implemented physically.  The device firmware must only respond
  1479.        to register commands as if a register were present.
  1480.  
  1481. »Register 0
  1482.  
  1483. Device register 0 is reserved for input data. If the device has user-input data to be
  1484. fetched, it places the data in register 0 and requests service. It continues to
  1485. request service until the system retrieves its data.  The system responds to data-input
  1486. requests with the following polling sequence:
  1487.  
  1488.   •  It generates a Talk command for register 0 in each device connected
  1489.      to the ADB.
  1490.   •  If the device has data to send, it responds.  The system does not
  1491.      poll the next device until the data is exhausted.
  1492.   •  If the device has no data to send, or if its data is exhausted, the
  1493.      VIA generates an interrupt.  The system then polls the next device.
  1494.   •  This process continues until no devices request service.
  1495.  
  1496. »Register 3
  1497.  
  1498. Device register 3 is reserved for device identification data and operating flags.
  1499. Application programs may set this data with Listen commands and read it with Talk
  1500. commands. Register 3 stores 16 bits, divided into the fields shown in Figure 2.
  1501.  
  1502. •••Refer to Figure 2.•••
  1503.  
  1504. Figure 2–Format of Device Register 3
  1505.  
  1506. Except for commands that contain certain reserved device handler ID values
  1507. (listed below), every command to register 3 changes the entire register contents.
  1508. Hence to change part of the register, you should first fetch its current contents
  1509. with a Talk command and then send it an updated value with Listen. You can change
  1510. part of the contents of register 3 by using special device handler ID values, as
  1511. described below.
  1512.  
  1513. The device handler ID field indicates the device’s type. With certain devices, an
  1514. application can change the device’s mode of operation by sending it a new ID value.
  1515. If the device supports the new mode, it stores the new value in this field.
  1516.  
  1517. Warning:  You are assigned handler IDs by Apple Software Licensing, so
  1518.           they do not conflict with the values of other devices that may
  1519.           be connected to the ADB at the same time.
  1520.  
  1521. When certain reserved values are sent to the device handler ID field by a Listen
  1522. command, they are not stored in the field; instead, they cause specific device actions.
  1523. Hence these values cannot be used as device ID values. They are the following:
  1524.  
  1525.   Value  Action
  1526.  
  1527.   $00    Change bits 8–13 of register 3 to match the rest of the command;
  1528.          leave Device Handler ID value unchanged.
  1529.   $FD    Change Device Address to match bits 8–11 if the device activator
  1530.          has been depressed; leave Device Handler ID value and flags unchanged.
  1531.   $FE    Change Device Address to match bits 8–11 if the result produces no
  1532.          address duplication on the bus; leave Device Handler ID value and
  1533.          flags unchanged.
  1534.   $FF    Initiate device self-test. If self-test succeeds, leave register 3
  1535.          unchanged; if self-test fails, clear Device Handler ID field to $00.
  1536.  
  1537. Other Device Handler ID values may be stored in the field.
  1538.  
  1539. Note:  Device Handler ID values below $20 are reserved by Apple.
  1540.  
  1541. The Device Address field indicates the device’s location within the 16 possible
  1542. device locations of the ADB. An application may change its value with a Listen command.
  1543. When this field is interrogated with a Talk command, it returns a random value. This
  1544. helps you separate multiple devices that have the same ADB address; for further
  1545. information, see “Device Addressing”, below.
  1546.  
  1547. The Service Request Enable bit is set by the device to request an interrupt poll.
  1548.  
  1549. _______________________________________________________________________________
  1550.  
  1551. »Device Addressing
  1552.  
  1553. There are 16 possible direct addresses, $00–$0F, for devices connected to the ADB.
  1554. However, it is possible to connect more than one device to an address; this might
  1555. happen, for example, in a system with two alternate keyboards.
  1556.  
  1557. When several devices share a single ADB address, but there are free addresses available
  1558. in the net, the system will automatically reassign addresses until they are all
  1559. different. It will do this every time the ADB Manager is initialized or reinitialized.
  1560. To find out a device’s new address, use the calls GetIndADB or GetADBInfo, described
  1561. later in this chapter.
  1562.  
  1563. _______________________________________________________________________________
  1564.  
  1565. »Standard ADB Device Drivers
  1566.  
  1567. The Macintosh II and Macintosh SE systems contain two standard ADB drivers:
  1568.  
  1569.   •  the mouse driver, which supports the ADB mouse. The Apple mouse
  1570.      has an original ADB address of 3.
  1571.   •  the universal keyboard driver, which supports all Apple ADB keyboards.
  1572.      The Apple keyboard has an original ADB address of 2, with a Device
  1573.      Handler ID of 1 for the Macintosh II keyboard and 2 for the Apple
  1574.      Extended Keyboard.  These keyboards are described in the Toolbox
  1575.      Event Manager chapter. 
  1576.  
  1577. These drivers reside in the system ROM. In addition, ADB address 0 is reserved for
  1578. the ADB chip itself.  You can change the ADB addresses of the mouse or keyboard, as
  1579. described above under “Device Registers,” but Apple does not recommend doing so.
  1580.  
  1581. Assembly-language note:  The ADB address of the keyboard on which the
  1582.                          last-typed character was entered is now stored
  1583.                          in the global variable KbdLast. The type of the
  1584.                          keyboard on which the last-typed character was
  1585.                          entered is stored in the global variable KbdType.
  1586.                          The value of KbdType is the Device Handler ID
  1587.                          value in Register 3 of the device; values below
  1588.                          $20 are reserved by Apple.
  1589.  
  1590. The requirements for writing new ADB device drivers are discussed later in this
  1591. chapter.
  1592.  
  1593. _______________________________________________________________________________
  1594.  
  1595.  
  1596. æKY ADB…Manager…Routines
  1597. æC »ADB MANAGER ROUTINES                                      AppleDesktopBus
  1598. _______________________________________________________________________________
  1599.  
  1600. The ADB Manager consists of six routines located in the 256K ROM. You would use them
  1601. only if you needed to access bus devices directly or communicate with a special
  1602. device.
  1603.  
  1604. Some of these routines access and update information in the ADB device table, a
  1605. structure placed in the system heap by ROM code during system  startup. It lists for
  1606. each device the device’s type, its original ADB address, its current ADB address, the
  1607. address of the routine that services the device, and the address of the area in RAM
  1608. used for temporary data storage by its driver. The ADB device table is accessible
  1609. only through ADB Manager routines.
  1610.  
  1611. PROCEDURE ADBReInit;
  1612.  
  1613. Trap macro    _ADBReInit
  1614.  
  1615. ADBReInit reinitializes the entire Apple Desktop Bus. It clears the ADB device table
  1616. to zeros and places a SendReset command on the bus to reset all devices to their
  1617. original addresses. ADBReInit has no parameters.
  1618.  
  1619. Because it does not deallocate ADB resources on the system heap, ADBReInit should not
  1620. be used for routine bus initialization. Apple strongly recommends against adding
  1621. devices while the system is running; therefore, you should never call ADBReInit.
  1622.  
  1623. ADBReInit also calls a routine pointed to by the low memory global JADBProc
  1624. at the beginning and end of its execution.  You can insert your own
  1625. preprocessing/postprocessing routine by changing the value of JADBProc; ADBReInit
  1626. conditions it by setting D0 to 0 for preprocessing and to 1 for postprocessing.  Your
  1627. procedure must restore the value of D0 and branch to the original value of JADBProc
  1628. on exit.  JADBProc should be used to de-allocate memory used by the driver (see
  1629. MacDTS Sample Code “TbltDrvr” for an example), and then it should chain to the procedure
  1630. originally found in JADBProc.
  1631.  
  1632. The complete ADBReInit sequence is therefore the following:
  1633.  
  1634.   •  JSR to JADBProc with D0 set to 0
  1635.   •  reinitialize the Apple Desktop Bus
  1636.   •  clear the ADB device table
  1637.   •  JSR to JADBProc with D0 set to 1
  1638.  
  1639. FUNCTION ADBOp (data: Ptr; compRout: ProcPtr; buffer: Ptr;
  1640.                 commandNum: INTEGER) : OSErr;
  1641.  
  1642. Trap macro    _ADBOp
  1643.  
  1644. On entry:    A0:  pointer to parameter block
  1645.              D0:  commandNum (byte)
  1646.  
  1647. Parameter block
  1648.     -->    0    buffer      pointer
  1649.     -->    4    compRout    pointer
  1650.     -->    8    data        pointer
  1651.  
  1652. On exit:     D0:  result code (byte)
  1653.  
  1654. The completion routine pointed to by compRout will be passed the following parameters
  1655. on entry:
  1656.  
  1657.              D0:  commandNum (byte)
  1658.              A0:  pointer to buffer, data stored as a Pascal string (maximum
  1659.                   8 bytes data preceded by one length byte)
  1660.              A1:  pointer to completion routine (compRout)
  1661.              A2:  pointer to optional data area (data)
  1662.  
  1663. ADBOp transmits over the bus the command byte whose value is given by commandNum. The
  1664. structure of the command byte is given earlier in Figure 1. ADBOp executes only when
  1665. the ADB is otherwise idle; otherwise it is held in a command queue. It returns an
  1666. error if the command queue is full. The length of the data buffer pointed to by
  1667. buffer is contained in its first byte, like a Pascal string. The optional data area
  1668. pointed to by data is for local storage by the completion routine pointed to by
  1669. compRout. ADBop should be used sparingly; it is not intended for polling a device. 
  1670. The host automatically polls devices with data to deliver.
  1671.  
  1672. Result codes    noErr    No error
  1673.                 –1       Unsuccessful completion
  1674.  
  1675. FUNCTION CountADBs: INTEGER;
  1676.  
  1677. Trap macro    _CountADBs
  1678.  
  1679. On exit:    D0:  number of devices (byte)
  1680.  
  1681. CountADBs returns a value representing the number of devices connected to the ADB by
  1682. counting the number of entries in the device table. It has no arguments and returns
  1683. no error codes.
  1684.  
  1685. FUNCTION GetIndADB (VAR info: ADBDataBlock;
  1686.                     devTableIndex: INTEGER) : ADBAddress;
  1687.  
  1688. Trap macro    _GetIndADB
  1689.  
  1690. On entry:    A0:  pointer to parameter block
  1691.              D0:  entry index number; range = 1..CountADBs (byte)
  1692.  
  1693. Parameter block
  1694.     <--    0    device type                byte    (handler ID)
  1695.     <--    1    original ADB address       byte
  1696.     <--    2    service routine address    pointer (compRout)
  1697.     <--    6    data area address          pointer (data)
  1698.  
  1699. On exit:     D0:  positive value:  current ADB address (byte)
  1700.                   negative value:  error code (byte)
  1701.  
  1702. GetIndADB returns information from the ADB device table entry whose index number is
  1703. given by devTableIndex. ADBDataBlock has this form:
  1704.  
  1705. TYPE  ADBDataBlock =
  1706.              PACKED RECORD
  1707.                devType:         SignedByte; {device type (handler ID)}
  1708.                origADBAddr:     SignedByte; {original ADB address}
  1709.                dbServiceRtPtr:  Ptr;        {service routine address (compRout)}
  1710.                dbDataAreaAddr:  Ptr         {data area address (data)}
  1711.              END;
  1712.  
  1713. GetIndADB returns the current ADB address of the device. If it is unable to complete
  1714. execution successfully, GetIndADB returns a negative value.
  1715.  
  1716. FUNCTION GetADBInfo (VAR info: ADBDataBlock; ADBAddr: ADBAddress) : OsErr;
  1717.  
  1718. Trap macro    _GetADBInfo
  1719.  
  1720. On entry:    A0:  pointer to parameter block
  1721.              D0:  ADB address of the device (byte)
  1722.  
  1723. Parameter block
  1724.     <--    0    device handler ID          byte
  1725.     <--    1    original ADB address       byte
  1726.     <--    2    service routine address    pointer (compRout)
  1727.     <--    6    data area address          pointer (data)
  1728.  
  1729. On exit:     D0:  result code (byte)
  1730.  
  1731. GetADBInfo returns information from the ADB device table entry of the device whose
  1732. ADB address is given by ABDAddr. The structure of ADBDataBlock is given above under
  1733. “GetIndADB”.
  1734.  
  1735. Result codes    noErr    No error
  1736.  
  1737. FUNCTION SetADBInfo (VAR info: ADBSetInfoBlock; ADBAddr: ADBAddress) : OsErr;
  1738.  
  1739. Trap macro    _SetADBInfo
  1740.  
  1741. On entry:    A0:  pointer to parameter block
  1742.              D0:  ADB address of the device (byte)
  1743.  
  1744. Parameter block
  1745.     -->    0    service routine address    pointer (compRout)
  1746.     -->    4    data area address          pointer (data)
  1747.  
  1748. On exit:     D0:  result code (byte)
  1749.  
  1750. SetADBInfo sets the service routine address and the data area address in the ADB
  1751. device table entry for the device whose ADB address is given by ABDAddr. ADBSetInfoBlock
  1752. has this form:
  1753.  
  1754. TYPE  ADBSetInfoBlock =
  1755.                RECORD
  1756.                  siServiceRtPtr:  Ptr;  {service routine address (compRout)}
  1757.                  siDataAreaAddr:  Ptr   {data area address (data)}
  1758.                END;
  1759.  
  1760. Result codes    noErr    No error
  1761.  
  1762. Warning:  You should send a Flush command to the device after calling it
  1763.           with SetADBInfo, to prevent it sending old data to the new data
  1764.           area address.
  1765.  
  1766. _______________________________________________________________________________
  1767.  
  1768.  
  1769. æKY Writing…ADB…Device…Drivers
  1770. æC »WRITING ADB DEVICE DRIVERS                                AppleDesktopBus
  1771. _______________________________________________________________________________
  1772.  
  1773. Drivers for devices connected to the ADB have the following special requirements:
  1774.  
  1775.   •  Each ADB device driver must reside in a resource of type 'ADBS'.
  1776.      (An example 'ADBS' resource is available in MacDTS Sample Code
  1777.      “TbltDrvr.”) This type has two sections: initialization and driver code.
  1778.   •  The initialization section of each ADB device driver must support the
  1779.      installation procedure described below.
  1780.  
  1781. When the system calls an ADB device driver, it passes it the following values:
  1782.  
  1783.   •  Register A0 points to the data buffer, which is formatted as a
  1784.      Pascal string (buffer).
  1785.   •  Register A1 points to the driver’s completion routine (compRout).
  1786.   •  Register A2 points to the optional data area (data).
  1787.   •  Register D0 contains the ADB command that resulted in the driver
  1788.      being called (commandNum).
  1789.  
  1790. The ADB driver should handle the ADB command passed to it and store any resulting
  1791. input data by an appropriate action, such as by posting an event or moving the cursor.
  1792.  
  1793. Note:  Events posted from keyboards connected to the ADB now have an
  1794.        expanded structure. For more information, see the Toolbox Event
  1795.        Manager chapter.
  1796.  
  1797. _______________________________________________________________________________
  1798.  
  1799. »Installing an ADB Driver
  1800.  
  1801. The Start Manager (described in this volume) finds all the ADB devices connected to
  1802. the system and places their device types and ADB addresses in the ADB device table.
  1803. It then calls the initialization section of each ADB device driver by executing the
  1804. initialization code in its 'ADBS' resource.
  1805.  
  1806. As a minimum, the initialization section of each ADB device driver must do the following:
  1807.  
  1808.   •  The driver must allocate all the memory required by the driver code
  1809.      in one or more nonrelocatable blocks in the system heap area.
  1810.   •  The driver must install its own preprocessing/postprocessing routine
  1811.      (if any) as described above under “ADBReInit”.
  1812.   •  Finally, the driver must initialize the service routine address and
  1813.      data area address of its entry in the ADB device table, using SetADBInfo.
  1814.  
  1815. _______________________________________________________________________________
  1816.  
  1817.  
  1818. æKY Summary…of…the…ADB
  1819. æC »SUMMARY OF THE ADB MANAGER                                AppleDesktopBus
  1820. _______________________________________________________________________________
  1821.  
  1822. Data Types
  1823.  
  1824. TYPE
  1825.   ADBDataBlock =
  1826.          PACKED RECORD
  1827.            devType:         SignedByte;  {Handler ID}
  1828.            origADBAddr:     SignedByte;  {original ADB address}
  1829.            dbServiceRtPtr:  Ptr;         {service routine address (compRout)}
  1830.            dbDataAreaAddr:  Ptr          {data area address (area)}
  1831.          END;
  1832.  
  1833.   ADBSetInfoBlock =
  1834.            RECORD
  1835.              siServiceRtPtr:  Ptr;  {service routine address}
  1836.              siDataAreaAddr:  Ptr   {data area address}
  1837.            END;
  1838.  
  1839. _______________________________________________________________________________
  1840.  
  1841. Routines
  1842.  
  1843. Initializing the ADB Manager
  1844.  
  1845. PROCEDURE ADBReInit;
  1846.  
  1847. Communicating Through the ADB
  1848.  
  1849. FUNCTION ADBOp (data: Ptr; compRout: ProcPtr; buffer: Ptr;
  1850.                 commandNum: INTEGER) : OSErr;
  1851.  
  1852. Getting ADB Device Information
  1853.  
  1854. FUNCTION CountADBs:  INTEGER;
  1855. FUNCTION GetIndADB   (VAR info: ADBDataBlock;
  1856.                       devTableIndex: INTEGER) : ADBAddress;
  1857. FUNCTION GetADBInfo  (VAR info: ADBDataBlock; ADBAddr: ADBAddress) : OsErr;
  1858.  
  1859. Setting ADB Device Information
  1860.  
  1861. FUNCTION SetADBInfo (VAR info: ADBSetInfoBlock; ADBAddr: ADBAddress) : OsErr;
  1862.  
  1863. _______________________________________________________________________________
  1864.  
  1865. Assembly-Language Information
  1866.  
  1867. Variables
  1868.  
  1869. JADBProc    Pointer to ADBReInit preprocessing/postprocessing routine
  1870. KbdLast     ADB address of the keyboard last used (byte)
  1871. KbdType     Keyboard type of the keyboard last used (byte)
  1872.  
  1873. Routines
  1874.  
  1875. Trap macro     On entry                               On Exit
  1876.  
  1877. _ADBReInit
  1878.  
  1879. _ADBOp         A0:  pointer to parameter block        D0:  result code (byte)
  1880.                     buffer (pointer)
  1881.                     compRout (pointer)
  1882.                     data (pointer)
  1883.                D0:  commandNum (byte)
  1884.  
  1885. _CountADBs                                            D0:  result code (byte)
  1886.  
  1887. _GetIndADB     A0:  pointer to parameter block        D0:  positive value:
  1888.                     device type (byte)                       current ADB
  1889.                     original ADB address (byte)              address (byte)
  1890.                     service routine address (pointer)        negative value:
  1891.                     data area address (pointer)              error code (byte)
  1892.                D0:  entry index number;
  1893.                     range = 1..CountADBs (byte)
  1894.  
  1895. _GetADBInfo    A0:  pointer to parameter block        D0:  result code (byte)
  1896.                     device handler ID (byte)           
  1897.                     original ADB address (byte)   
  1898.                     service routine address (pointer)   
  1899.                     data area address (pointer)
  1900.                D0:  current ADB address of the device (byte)
  1901.  
  1902. _SetADBInfo    A0:  pointer to parameter block        D0:  result code (byte)
  1903.                     service routine address (pointer)   
  1904.                     data area address (pointer)
  1905.                D0:  current ADB address of the device (byte)
  1906.  
  1907. Further Reference:
  1908. _______________________________________________________________________________
  1909. Toolbox Event Manager
  1910. Technical Note #143, Don’t Call ADBReInit on the SE with System 4.1
  1911. Technical Note #160, Key Mapping
  1912. Technical Note #206, Space Aliens Ate My Mouse
  1913. “Macintosh Family Hardware Reference”
  1914.  
  1915.  
  1916. æKY AppleEventManager
  1917. æC 
  1918. _______________________________________________________________________________
  1919.  
  1920. THE APPLE EVENT MANAGER
  1921. _______________________________________________________________________________
  1922.  
  1923. About…the…Apple…Event…Manager…Chapter…Volume…VI
  1924. About…the…Apple…Event…Manager…Volume…VI
  1925. Introduction…to…Apple…Events…Volume…VI
  1926.     Types…of…Apple…Events
  1927.     Components…of…Apple…Events
  1928.     Data…Structures…Within…Apple…Events
  1929.     Responding…to…Apple…Events
  1930.     Requesting…Services…Through…Apple…Events
  1931. Using…the…Apple…Event…Manager…Volume…VI
  1932.     Accepting…an…Apple…Event
  1933.     Installing…Entries…Into…the…Apple…Event…Dispatch…Tables
  1934.     Handling…the…Required…Apple…Events
  1935.         Required…Apple…Events
  1936.         Handling…the…Open…Application…Event
  1937.         Handling…the…Open…Documents…Event
  1938.         Handling…the…Print…Documents…Event
  1939.         Handling…the…Quit…Application…Event
  1940.         Handling…Apple…Events…Sent…by…the…Edition…Manager
  1941.         Handling…the…Create…Publisher…Event
  1942.     Getting…Data…out…of…an…Apple…Event
  1943.         Getting…Data…out…of…a…Parameter
  1944.         Getting…Data…out…of…an…Attribute
  1945.         Getting…Data…out…of…a…Descriptor…List
  1946.     Writing…Apple…Event…Handlers
  1947.     Replying…to…an…Apple…Event
  1948.     Disposing…of…Apple…Event…Data…Structures
  1949.     Interacting…With…the…User
  1950.     Creating…an…Apple…Event
  1951.         Adding…Parameters…to…an…Apple…Event
  1952.         Specifying…a…Target…Address
  1953.     Sending…an…Apple…Event
  1954.     Dealing…With…Timeouts
  1955.     Writing…an…Idle…Function
  1956.     Writing…a…Reply…Filter…Function
  1957.     Writing…and…Installing…Coercion…Handlers
  1958.     The…Application…Died…Event
  1959. Apple…Event…Manager…Routines…Volume…VI
  1960.     Creating…and…Managing…the…Apple…Event…Dispatch…Tables
  1961.     Dispatching…Apple…Events
  1962.     Getting…Parameters…and…Attributes…From…Apple…Events
  1963.     Counting…the…Items…in…Descriptor…Lists
  1964.     Getting…Items…From…Descriptor…Lists
  1965.     Getting…Data…From…AE…Records
  1966.     Requesting…User…Interaction
  1967.     Requesting…More…Time…to…Respond…to…Apple…Events
  1968.     Suspending…and…Resuming…Apple…Event…Handling
  1969.     Creating…Apple…Events
  1970.     Creating…and…Duplicating…Descriptor…Records
  1971.     Creating…Descriptor…Lists…and…AE…Records
  1972.     Adding…Items…to…Descriptor…Lists
  1973.     Adding…Data…to…AE…Records
  1974.     Adding…Parameters…and…Attributes…to…Apple…Events
  1975.     Sending…Apple…Events
  1976.     Getting…the…Sizes…and…Descriptor…Types…of…Descriptor…Records
  1977.     Deleting…Descriptor…Records
  1978.     Deallocating…Memory…for…Descriptor…Records
  1979.     Coercing…Descriptor…Types
  1980.     Creating…and…Managing…the…Coercion…Handler…Tables
  1981.     Creating…and…Managing…the…Special…Handler…Tables
  1982. Summary…of…the…Apple…Events…Manager…Volume…VI
  1983.     Apple…Events…Manager…Constants
  1984.     Apple…Events…Manager…Data…Types
  1985.     Apple…Events…Manager…Routines…Summary
  1986.     Apple…Events…Manager…Result…Codes
  1987.     Apple…Events…Manager…Assembly-Language…Information
  1988. _______________________________________________________________________________
  1989.  
  1990.  
  1991.  
  1992. æKY About…the…Apple…Event…Manager…Chapter…Volume…VI
  1993. æC »About the Apple Event Manager Chapter Volume VI                The Apple Event Manager
  1994. _______________________________________________________________________________
  1995.  
  1996. This chapter describes Apple® events and how your application can use the Apple
  1997. Event Manager to receive and process the required set of Apple events sent by
  1998. the Finder™. This chapter also describes how to use the Apple Event Manager to
  1999. send Apple events to other applications and how to process Apple events received
  2000. from other applications.
  2001.  
  2002. As explained in the Event Manager chapter in this volume, the Event Manager in
  2003. system software version 7.0 introduces high-level events, along with a number of
  2004. new Event Manager routines that let applications communicate with each other by
  2005. sending high-level events. Using Event Manager routines, your application can
  2006. create and process its own high-level events.
  2007.  
  2008. However, effective interapplication communication requires that applications
  2009. agree on a standard set of conventions—a common vocabulary. To provide such a
  2010. standard, Apple Computer, Inc., has defined a protocol called the Apple Event
  2011. Interprocess Messaging Protocol (AEIMP). High-level events that adhere to this
  2012. protocol are called Apple events.  You can help ensure effective communication
  2013. with other applications by using this protocol..
  2014.  
  2015. System software uses Apple events to communicate information to your
  2016. application; you should support the required set of Apple events sent by the
  2017. Finder to your application. In addition, you can support Apple events that are
  2018. common to many applications. Using the routines of the Apple Event Manager, you
  2019. can use Apple events to communicate with other applications in a standard way.
  2020. Using Apple events to ensure better cooperation between your application and
  2021. other applications helps users to get the most out of any one application or to
  2022. use the best features from many applications—in effect, combining the features
  2023. of many applications to achieve the desired result.
  2024.  
  2025. By following the standards specified by AEIMP, you can also define your own
  2026. Apple events. You can choose to publish these so that other applications can use
  2027. them, or you may choose to keep them unpublished for exclusive use by your own
  2028. applications.
  2029.  
  2030. The Apple Event Manager is available only in system software version 7.0. To
  2031. determine whether the Apple Event Manager is available, use the Gestalt function
  2032. described in the Compatibility Guidelines chapter of this volume.
  2033.  
  2034. The interapplication communications architecture of system software version 7.0
  2035. consists of three main components: the Apple Event Manager, the Event Manager,
  2036. and the Program-to-Program Communications (PPC) Toolbox. See the Introduction to
  2037. the System Software Version 7.0 Environment chapter in this volume for an
  2038. overview of the relationships among these components. If you intend to use
  2039. high-level events that do not rely on AEIMP, read the Event Manager chapter of
  2040. this volume. This chapter describes the information you need to know to support
  2041. Apple events in your application. To allow your application to send Apple events
  2042. to applications on remote computers, you may wish to use the PPCBrowser
  2043. function, which is described in the Program-to-Program Communications Toolbox
  2044. chapter of this volume.
  2045.  
  2046. While the Apple events used by the Edition Manager are discussed in this
  2047. chapter, you must refer to the Edition Manager chapter of this volume for a full
  2048. discussion of how to implement the Edition Manager’s publish and subscribe
  2049. features.
  2050.  
  2051. For descriptions of all publicly available Apple events, see the Apple Event
  2052. Registry,  available from Macintosh® Developer Technical Support.
  2053.  
  2054. _______________________________________________________________________________
  2055.  
  2056. æKY About…the…Apple…Event…Manager…Volume…VI
  2057. æC »About the Apple Event Manager Volume VI                        The Apple Event Manager
  2058. _______________________________________________________________________________
  2059.  
  2060. Apple events provide your application with a standard mechanism for
  2061. communicating with other applications. You can use Apple events and the Apple
  2062. Event Manager to
  2063.  
  2064.   • respond to the required Apple events (Open Application, Open Documents,
  2065.      Print Documents, and Quit Application) that are sent by the Finder
  2066.  
  2067.   • respond to the Apple events sent by the Edition Manager and allow users to
  2068.      share data among documents created by multiple applications
  2069.  
  2070.   • provide services to other applications
  2071.  
  2072.   • request services from other applications
  2073.  
  2074. By supporting the required Apple events, your application can take advantage of
  2075. the more reliable launch and termination mechanisms built into system software
  2076. version 7.0. You can also take advantage of the services provided by the Edition
  2077. Manager by responding to the Apple events sent by the Edition Manager. These and
  2078. additional core Apple events can be used by nearly all applications to
  2079. communicate with system software or with other applications.
  2080.  
  2081. You can also support functional-area Apple events related to your application in
  2082. order to provide services to other applications or to request services from
  2083. other applications. Finally, if your application defines Apple events for all
  2084. the actions that a user can perform, you can record user actions by generating
  2085. the corresponding Apple event for each action, saving a copy of the Apple event,
  2086. and then sending the Apple event to your own application for handling. Apple
  2087. events that are recorded in this way can later be played back to automate tasks
  2088. previously performed by the user.
  2089.  
  2090. To support Apple events in your application, you must
  2091.  
  2092.   • decide which Apple events (in addition to the required ones) to support
  2093.  
  2094.   • set bits in the 'SIZE' resource to indicate that your application supports 
  2095.      high-level events
  2096.  
  2097.   • create an Apple event dispatch table
  2098.  
  2099.   • include code to handle high-level events in your main event loop
  2100.  
  2101.   • handle the Apple events your application receives and wishes to support
  2102.  
  2103.   • create the Apple events you wish your application to generate
  2104.  
  2105. This chapter begins with an introduction to Apple events and then describes
  2106.  
  2107.   • the required Apple events that your application must support to be
  2108.   7.0-friendly
  2109.  
  2110.   • how to use the Apple Event Manager to send and process Apple events
  2111. _______________________________________________________________________________
  2112.  
  2113. æKY Introduction…to…Apple…Events…Volume…VI
  2114. æC »Introduction to Apple Events Volume VI                         The Apple Event Manager
  2115. _______________________________________________________________________________
  2116.  
  2117. Applications typically use Apple events to request services from and provide
  2118. services to other applications. For example, the Open Documents event, sent by
  2119. the Finder, requests that your application open specified documents. When your
  2120. application supports this Apple event, it should respond by opening those
  2121. documents in the manner that your application normally opens documents.
  2122.  
  2123. A transaction involving Apple events is initiated by a client application, which
  2124. sends an Apple event to request a service (for example, printing a list of
  2125. files, spell-checking a list of words, or performing a numerical calculation).
  2126. The application providing the service is called a server application. These
  2127. applications can reside on the same local computer or on remote computers
  2128. connected to a network.
  2129.  
  2130. Figure 6-1 shows a common Apple event, the Open Documents event. You see that
  2131. the Finder application is the client; it requests that the SurfWriter
  2132. application open the documents named Dec. Invoice and Nov. Invoice. The
  2133. SurfWriter application responds to the Finder’s request by opening windows
  2134. containing the specified documents.
  2135.  
  2136. ¿ Figure 6-1   An Open Documents event ø 
  2137.  
  2138. The Finder is also the source application of the Open Documents event. A source
  2139. application is one that sends an Apple event to another application or to
  2140. itself. In Figure 6-1, the SurfWriter application is the target application of
  2141. the event. The target application is the one addressed to receive the Apple
  2142. event. The terms client application  and source application  are not always
  2143. synonymous, nor are the terms server application  and target application.
  2144. Typically, an Apple event client sends an Apple event requesting a service from
  2145. an Apple event server; in this case, the server is the target application of the
  2146. Apple event. The Apple event server may send back a different Apple event as a
  2147. response—in which case, the client becomes the target of the responding Apple
  2148. event.
  2149.  
  2150. _______________________________________________________________________________
  2151.  
  2152. æKY Types…of…Apple…Events
  2153. æC »Types of Apple Events                                          The Apple Event Manager
  2154. _______________________________________________________________________________
  2155.  
  2156. Apple events fall into one of several broad categories.
  2157.  
  2158.   • Required Apple events consist of four core Apple events that the Finder
  2159.   sends
  2160.      to applications. These events are called Open Documents, Open Application,
  2161.      Print Documents, and Quit Application. They are a subset of the core Apple
  2162.      events and are described in detail later in this chapter.
  2163.  
  2164.   • Core Apple events are used by nearly all applications to communicate. The
  2165.   suite
  2166.      of core Apple events is described in the Apple Event Registry;  Apple
  2167.      recommends that all applications support the core Apple events.
  2168.  
  2169.   • Functional-area Apple events are supported by applications with related
  2170.      features. Apple events related to text manipulation for word-processing
  2171.      applications and Apple events related to graphics manipulation for drawing
  2172.      applications are examples of functional-area Apple events. Functional-area
  2173.      Apple events are defined by Apple in consultation with interested
  2174.      developers
  2175.      and are published in the Apple Event Registry. Apple recommends that all
  2176.      developers support functional-area Apple events appropriate for their types
  2177.      of
  2178.      applications.
  2179.  
  2180.   • Custom Apple events are defined by a developer for use by the developer’s
  2181.   own
  2182.      applications. You should register all of your custom Apple events with
  2183.      Macintosh Developer Technical Support. You can choose to publish your Apple
  2184.      events in the Apple Event Registry  so that other applications can share
  2185.      them, or
  2186.      you may choose to keep them unpublished for exclusive use by your own
  2187.      applications.
  2188. _______________________________________________________________________________
  2189.  
  2190. æKY Components…of…Apple…Events
  2191. æC »Components of Apple Events                                     The Apple Event Manager
  2192. _______________________________________________________________________________
  2193.  
  2194. An Apple event consists of attributes (which identify the Apple event and denote
  2195. its task) and, often, parameters (which contain data to be used by the target
  2196. application). An application uses the Apple Event Manager to create an Apple
  2197. event. Using arguments you pass to the AECreateAppleEvent function and to other
  2198. Apple Event Manager routines, the Apple Event Manager constructs the necessary
  2199. data structures containing attributes and parameters and converts these
  2200. structures into an Apple event. Applications must use the Apple Event Manager’s
  2201. AESend function to transmit the Apple event. After receiving an Apple event,
  2202. applications must use Apple Event Manager routines to extract the attributes and
  2203. parameters of the event.
  2204.  
  2205. Attributes are a fundamental component of Apple events. Apple event attributes
  2206. are records that identify the event class, event ID, target application, and
  2207. other characteristics of an Apple event. Taken together, the attributes of an
  2208. Apple event denote the task to be performed on any data specified in the Apple
  2209. event’s parameters. You do not have any direct way to access the data stored in
  2210. these records. You must use Apple Event Manager routines to extract or specify
  2211. the attributes.
  2212.  
  2213. An Apple event parameter is a record containing data that the target application
  2214. uses. Unlike Apple event attributes (which contain information that can be used
  2215. by both the Apple Event Manager and the target application), Apple event
  2216. parameters contain data used only by the target application. For example, an
  2217. attribute like the event ID is used by the Apple Event Manager to call a handler
  2218. from the server application’s dispatch table, and the server application must
  2219. have a handler to process the event identified by that attribute. By comparison,
  2220. the list of documents contained in a parameter to an Open Documents event is
  2221. used only by the server application. As with attributes, you do not have any
  2222. direct way to access the data structure of a parameter. You have to use Apple
  2223. Event Manager functions to extract or put data into parameters.
  2224.  
  2225. Note that Apple event parameters are different from the parameters of Apple
  2226. Event Manager functions. Apple event parameters are records private to the Apple
  2227. Event Manager; function parameters are arguments you pass to the function or
  2228. that the function returns to you. You typically specify the Apple event
  2229. parameters (as well as the attributes) in parameters to Apple Event Manager
  2230. functions. For example, the AEGetParamPtr function uses a buffer to return the
  2231. data contained in an Apple event parameter. You specify which Apple event
  2232. parameter in one of the parameters of the AEGetParamPtr function.
  2233.  
  2234. Apple events are identified by their event class and event ID attributes. The
  2235. event class is the attribute that identifies a group of related Apple events.
  2236. The event class appears in the message field of the event record for an Apple
  2237. event. For example, the four required Apple events (in fact, all core Apple
  2238. events) have the value 'aevt' in the message fields of their event records. The
  2239. value 'aevt' can also be represented by the kCoreEventClass constant. Several
  2240. event classes are shown here.
  2241.  
  2242.    Event class                            Value        Description
  2243.  
  2244.    kCoreEventClass                 'aevt'        A core Apple event
  2245.    kAEFinderEvents               'FNDR'    An event that the Finder accepts
  2246.    kSectionEventMsgClass    'sect'         An event sent by the Edition Manager
  2247.  
  2248. The event ID is the attribute that identifies the particular Apple event within
  2249. its event class. In conjunction with the event class, the event ID uniquely
  2250. identifies the Apple event and communicates what action the Apple event should
  2251. perform. (The event IDs appear in the where field of the event record for an
  2252. Apple event.) For example, the event ID of an Open Documents event has the value
  2253. 'odoc' (which can also be represented by the kAEOpenDocuments constant). The
  2254. kCoreEventClass constant in combination with the kAEOpenDocuments constant
  2255. identifies the Open Documents event to the Apple Event Manager.
  2256.  
  2257. Shown here are the event IDs for the four required Apple events.
  2258.  
  2259.    Event ID                             Value        Description
  2260.  
  2261.    kAEOpenApplication      'oapp'       Open your application
  2262.    kAEOpenDocuments       'odoc'       Open documents
  2263.    kAEPrintDocuments        'pdoc'       Print documents
  2264.    kAEQuitApplication        'quit'         Quit your application
  2265.  
  2266. The target application’s address is another required attribute. As previously
  2267. described, the target application is the one addressed to receive the Apple
  2268. event. Your application can send an Apple event to itself or to another
  2269. application (on the same computer or on a remote computer connected to the
  2270. network).
  2271.  
  2272. As with attributes, there are various types of Apple event parameters. A direct
  2273. parameter contains the data to be acted upon by the server application. For
  2274. example, a list of documents is contained in the direct parameter of the Print
  2275. Documents event. Direct parameters are usually required parameters—parameters
  2276. that the server application needs in order to carry out the task denoted by the
  2277. Apple event. Some Apple events also take additional parameters, which the server
  2278. application uses in addition to the data specified in the direct parameter. For
  2279. example, an Apple event for arithmetic operations may include additional
  2280. parameters that specify operands in an equation. Additional parameters may be
  2281. required or optional.
  2282.  
  2283. An optional parameter is a supplemental parameter that also can be used to
  2284. specify data to the server application. Optional parameters need not be included
  2285. in an Apple event; default values for optional parameters are part of the event
  2286. definition. The server application that handles the event must supply default
  2287. values if the optional parameters are omitted.
  2288.  
  2289. Figure 6-2 shows in greater detail the components of the Open Documents event
  2290. that was introduced in Figure 6-1.
  2291.  
  2292. ¿ Figure 6-2   Major components of an Open Documents event ø 
  2293.  
  2294. To process the information contained in the Open Documents event, the SurfWriter
  2295. application uses the AEProcessAppleEvent function. The AEProcessAppleEvent
  2296. function provides an easy way for your application to identify the event class
  2297. and event ID of the Apple event and to direct the Apple Event Manager to call
  2298. the code in your program that handles the Apple event.
  2299. _______________________________________________________________________________
  2300.  
  2301. æKY Data…Structures…Within…Apple…Events
  2302. æC »Data Structures Within Apple Events                            The Apple Event Manager
  2303. _______________________________________________________________________________
  2304.  
  2305. Applications must use Apple Event Manager functions to create and send an Apple
  2306. event. The Apple Event Manager constructs its own internal data structures to
  2307. contain the information in an Apple event. To gain access to this data, the
  2308. target application also must use Apple Event Manager functions. Neither the
  2309. sender nor the receiver of an Apple event can directly manipulate the data
  2310. inside an Apple event; each must rely on Apple Event Manager functions to do so.
  2311. This section describes the data structures that the Apple Event Manager uses to
  2312. create and to process Apple events.
  2313.  
  2314. Descriptor records are the fundamental structures from which Apple events are
  2315. constructed. A descriptor record is a data structure of type AEDesc; it consists
  2316. of a handle to data and a descriptor type that identifies the type of the data
  2317. referred to by the handle.
  2318.  
  2319. TYPE AEDesc = 
  2320.      RECORD
  2321.         descriptorType:   DescType;   {type of data being passed}
  2322.         dataHandle:       Handle      {handle to data being passed}
  2323. END;
  2324.  
  2325. The data referred to by the dataHandle field in the descriptor record is private
  2326. to the Apple Event Manager. You can supply or extract this data only by using
  2327. Apple Event Manager routines.
  2328.  
  2329. The descriptor type is a structure of type DescType, which in turn is of data
  2330. type ResType—that is, a four-character string. Constants are usually used in
  2331. place of these four-character strings when referring to descriptor types.
  2332. Descriptor types represent various data types. Here is a list of descriptor type
  2333. constants, their values, and the types of data they represent.
  2334.  
  2335.    Descriptor type                 Value       Description
  2336.  
  2337.    typeBoolean                      'bool'        Boolean value
  2338.    typeChar                            'TEXT'      Unterminated string
  2339.    typeSMInt                         'shor'        16-bit integer
  2340.    typeInteger                        'long'        32-bit integer
  2341.    typeSMFloat                      'sing';       SANE Single
  2342.    typeFloat                            'doub';      SANE Double
  2343.    typeLongInteger               'long'        32-bit integer
  2344.    typeShortInteger              'shor'        16-bit integer
  2345.    typeLongFloat                   'doub'       SANE Double
  2346.    typeShortFloat                  'sing'         SANE Single
  2347.    typeExtended                     'exte'         SANE Extended
  2348.    typeComp                           'comp'      SANE Comp
  2349.    typeMagnitude                  'magn'      Unsigned 32-bit integer
  2350.    typeAEList                          'list'           List of descriptor
  2351.    records
  2352.    typeAERecord                    'reco'         List of keyword-specified
  2353.    descriptor records
  2354.    typeAppleEvent                 'aevt'        Apple event record
  2355.    typeTrue                              'true'         TRUE Boolean value
  2356.    typeFalse                              'fals'          FALSE Boolean value
  2357.    typeAlias                              'alis'          Alias record
  2358.    typeEnumerated                'enum'      Enumerated data
  2359.    typeType                              'type'          Four-character code for
  2360.    event class or event
  2361.                                                                       ID
  2362.    typeAppParameters           'appa'        Process Manager launch parameters
  2363.    typeProperty                        'prop'        Apple event property
  2364.    typeFSS                                 'fss '           File system
  2365.    specification
  2366.    typeKeyword                       'keyw'       Apple event keyword
  2367.    typeSectionH                       'sect'         Handle to a section record
  2368.    typeTemporaryID               'tid '          Temporary ID
  2369.    typeWildCard                      '****'        Matches any type
  2370.    typeApplSignature             'sign'        Application signature
  2371.    typeSessionID                      'ssid'         Session ID
  2372.    typeTargetID                        'targ'         Target ID record
  2373.    typeProcessSerialNumber  'psn '       Process serial number
  2374.    typeNull                               'null'         NULL or nonexistent
  2375.    data
  2376.  
  2377. Figure 6-3 illustrates a descriptor record with a descriptor type of typeType,
  2378. which specifies that the data in the descriptor record must consist of a
  2379. four-character code. The data in this particular descriptor record is specified
  2380. by the constant kCoreEventClass, whose value is 'aevt'.
  2381.  
  2382. ¿ Figure 6-3   A descriptor record with event class data ø 
  2383.  
  2384. A descriptor record that contains the address of the target or source of an
  2385. Apple event is called  an address descriptor record.
  2386.  
  2387.    TYPE  AEAddressDesc = AEDesc;              {address descriptor record}
  2388.  
  2389. As you will see later, the address can be specified as an application signature,
  2390. a process serial number, a session ID, a target ID record, or a data type that
  2391. you define.
  2392.  
  2393. Data for attributes and parameters are contained in descriptor records. The
  2394. attributes and parameters themselves are identified by keywords. The AEKeyword
  2395. data type is defined as a four-character code.
  2396.  
  2397.    TYPE  AEKeyword = PACKED ARRAY[1..4] OF Char;
  2398.                                               {keyword for a descriptor }
  2399.                                               { record}
  2400.  
  2401. Constants are typically used for keywords. Shown here is a list of these keyword
  2402. constants, their four-character codes, and the attributes and parameters they
  2403. represent.
  2404.  
  2405.    Attribute keyword                Value      Description
  2406.  
  2407.    keyAddressAttr                     'addr'      Address of target application
  2408.    keyEventClassAttr                'evcl'      Event class of Apple event
  2409.    keyEventIDAttr                     'evid'      Event ID of Apple event
  2410.    keyEventSourceAttr             'esrc'       Source of the Apple event
  2411.    keyInteractLevelAttr             'inte'      Settings for allowing the Apple
  2412.    Event
  2413.                                                                       Manager to
  2414.                                                                       bring a
  2415.                                                                       server
  2416.  
  2417.                                                                       to the
  2418.                                                                       foreground
  2419.    keyMissedKeywordAttr       'miss'     First required parameter remaining in
  2420.    an
  2421.                                                                       Apple
  2422.                                                                       event
  2423.    keyOptionalKeywordAttr    'optk'     List of optional parameters for the
  2424.    Apple 
  2425.                                                                       event
  2426.    keyReturnIDAttr                   'rtid'       Return ID for reply Apple
  2427.    event 
  2428.    keyTimeoutAttr                     'timo'    Length of time in ticks that the
  2429.    client will 
  2430.                                                                       wait for a
  2431.                                                                       reply or a
  2432.                                                                       result
  2433.                                                                       from the
  2434.                                                                       server
  2435.    keyTransactionIDAttr           'tran'     Transaction ID identifying a series
  2436.    of Apple 
  2437.                                                                       events
  2438.  
  2439.    Parameter keyword               Value     Description
  2440.  
  2441.    keyDirectObject                      '––––'     Direct parameter
  2442.    keyErrorNumber                   'errn'      Error number parameter
  2443.    keyErrorString                        'errs'       Error string parameter
  2444.    keyProcessSerialNumber     'psn '      Process serial number parameter
  2445.  
  2446. A data structure of type AEKeyDesc consists of a keyword and a descriptor
  2447. record. This data structure, called a keyword-specified descriptor record, is
  2448. used by the Apple Event Manager to fully identify and describe an attribute or a
  2449. parameter of an Apple event.
  2450.  
  2451.    TYPE  AEKeyDesc =        {keyword-specified descriptor record}
  2452.          RECORD
  2453.             descKey:         AEKeyword;      {keyword}
  2454.             descContent:     AEDesc          {descriptor record};
  2455.    END;
  2456.  
  2457. Figure 6-4 illustrates a keyword-specified descriptor record for the event class
  2458. attribute of an Open Documents event. The keyEventClassAttr keyword identifies
  2459. its descriptor record as containing event class data. The data is of the
  2460. typeType descriptor type, and the data identifies the event class as
  2461. kCoreEventClass.
  2462.  
  2463. ¿ Figure 6-4   A keyword-specified descriptor record for the event class
  2464. attribute of an Open Documents event ø 
  2465.  
  2466. When extracting data from an Apple event, you use Apple Event Manager functions
  2467. to return data in a buffer specified by a pointer, or to return descriptor
  2468. records containing the data, or to return lists of descriptor records (called
  2469. descriptor lists) containing the data. As previously noted, the descriptor
  2470. record (of data type AEDesc) is the fundamental structure in Apple events, and
  2471. it contains a handle to data. A descriptor list is a data structure of type
  2472. AEDescList defined by the data type AEDesc—that is, a descriptor list is a
  2473. descriptor record that contains a list of other descriptor records.
  2474.  
  2475.    TYPE  AEDescList = AEDesc;  {list of descriptor records}
  2476.  
  2477. An example of a descriptor list that you will be using is the direct parameter
  2478. for the Open Documents event. As illustrated in Figure 6-5, this descriptor list
  2479. is a list of descriptor records that contain alias records to filenames. (The
  2480. Alias Manager chapter of this volume describes alias records in detail.)
  2481.  
  2482. ¿ Figure 6-5   A descriptor list for a list of aliases ø 
  2483.  
  2484. Closely related to a descriptor list is a structure of data type AERecord; in
  2485. fact, it is defined by the data type AEDescList.
  2486.  
  2487.    TYPE  AERecord = AEDescList;    {list of keyword-specified }
  2488.                                    { descriptor records}
  2489.  
  2490. While a descriptor list is a descriptor record that contains a list of other
  2491. descriptor records, an AE record of data type AERecord contains a list of
  2492. keyword-specified descriptor records describing parameters. A descriptor list of
  2493. data type AERecord contains no attributes, only parameters.
  2494.  
  2495. There is one final data structure to consider: the Apple event record. An Apple
  2496. event record is a structure of data type AppleEvent defined as an AE record. It
  2497. is used for describing a full-fledged Apple event.
  2498.  
  2499.    TYPE  AppleEvent = AERecord;  {list of attributes and parameters }
  2500.                                  { necessary for an Apple event}
  2501.  
  2502. An Apple event record is basically a descriptor record (of descriptor type
  2503. typeAppleEvent) with a handle to a list of keyword-specified descriptor records.
  2504. These descriptor records describe the attributes and parameters for an Apple
  2505. event. When you use the AECreateAppleEvent function, the Apple Event Manager
  2506. creates an Apple event record containing the attributes for an Apple event’s
  2507. event class, event ID, target address, return ID, and transaction ID. You then
  2508. use Apple Event Manager functions such as AEPutParamDesc to add parameters to
  2509. the Apple event. Figure 6-6 shows an example of an Apple event—a structure
  2510. containing a list of keyword-specified descriptor records that name the
  2511. attributes and parameters of an Open Documents event.
  2512.  
  2513. ¿ Figure 6-6   Data structures within an Open Documents event ø 
  2514.  
  2515. The internal structure of an Apple event record is nearly identical to an AE
  2516. record. They differ in the content referred to by the data handles that they
  2517. contain: the former has a list of attributes and, possibly, parameters referred
  2518. by its handle; the latter contains only parameters. However, you can pass an
  2519. Apple event record to any Apple Event Manger function that expects an AE record.
  2520. Since both are structures of data type AEDescList, which is derived from the
  2521. data type AEDesc, you can pass Apple event records, AE records, descriptor
  2522. lists, and descriptor records to any Apple Event Manager functions that expect
  2523. records of data type AEDesc.
  2524.  
  2525. The data in Apple event records, AE records, and descriptor lists—all of which
  2526. are descriptor records—is private to the Apple Event Manager. The Apple Event
  2527. Manager maintains these different data structures because it stores different
  2528. kinds of information in their handles. Although all the information you need is
  2529. available by calling the appropriate Apple Event Manager functions, the Apple
  2530. Event Manager needs a way to tell these different descriptor records apart. It
  2531. does this by looking at their data types.
  2532. _______________________________________________________________________________
  2533.  
  2534. æKY Responding…to…Apple…Events
  2535. æC »Responding to Apple Events                                     The Apple Event Manager
  2536. _______________________________________________________________________________
  2537.  
  2538. A client application uses the Apple Event Manager to create and send an Apple
  2539. event requesting a service. A server application responds by using the Apple
  2540. Event Manager to process the Apple event, to extract data from the attributes
  2541. and parameters of the Apple event, and to return a result to the client
  2542. application. The server provides its own routines for performing the action
  2543. requested by the client’s Apple event.
  2544.  
  2545. As its first step in supporting Apple events, your application must be able to
  2546. respond to the required Apple events sent by the Finder. If you plan to
  2547. implement publish and subscribe capabilities, your application must respond to
  2548. the Apple events sent by the Edition Manager. You can also respond to Apple
  2549. events sent by your own application or by other applications. This section
  2550. provides a quick overview of the steps your application takes in responding to
  2551. Apple events.
  2552.  
  2553. To respond to Apple events, your application must
  2554.  
  2555.   • test for high-level events in its event loop
  2556.  
  2557.   • use the AEProcessAppleEvent function to process Apple events
  2558.  
  2559.   • provide handler routines for the Apple events it supports
  2560.  
  2561.   • use Apple Event Manager functions to extract the parameters and attributes 
  2562.      from Apple events
  2563.  
  2564.   • use the AEInteractWithUser function—if your application requires input from 
  2565.      the user when your application is responding to an Apple event—to bring
  2566.      your 
  2567.      application to the foreground to interact with the user
  2568.  
  2569.   • return a result for the client
  2570.  
  2571. Note that in order for your application to respond to Apple events sent from
  2572. remote computers, the user of your application must allow network users to link
  2573. to your application. The user does this by selecting your application from the
  2574. Finder and choosing Sharing from the File menu and then clicking the Allow
  2575. Remote Program Linking checkbox. If the user has not yet started program
  2576. linking, the Sharing command offers to display the Sharing Setup control panel
  2577. so that the user can start program linking. The user must also authorize remote
  2578. users for program linking by using the Users and Groups control panel. Program
  2579. linking and setting up authenticated sessions are described in the
  2580. Program-to-Program Communications chapter in this volume.
  2581.  
  2582. An Apple event (like all high-level events) is identified by a message class of
  2583. kHighLevelEvent in the what field of the event record. You test the what field
  2584. of the event record to determine whether an event is a high-level event. If the
  2585. what field contains the kHighLevelEvent constant and your application defines
  2586. any high-level events other than Apple events, test the message field of the
  2587. event record to determine whether the high-level event is something other than
  2588. an Apple event. If the high-level event is not one that you’ve defined for your
  2589. application, assume that it is an Apple event. (Note that you are encouraged to
  2590. use Apple events instead of defining your own high-level events whenever
  2591. possible.)
  2592.  
  2593. After determining that an event is an Apple event, use the AEProcessAppleEvent
  2594. function to let the Apple Event Manager identify the event. Figure 6-7 shows how
  2595. the SurfWriter application accepts and begins to process an Apple event sent by
  2596. the Finder.
  2597.  
  2598. ¿ Figure 6-7   Accepting and processing an Open Documents event ø 
  2599.  
  2600. The AEProcessAppleEvent function begins processing the Apple event. The
  2601. AEProcessAppleEvent function identifies the Apple event by examining the data in
  2602. the event class and event ID attributes. The AEProcessAppleEvent function in
  2603. turn uses that data to call the Apple event handler that your application
  2604. provides for that event. An Apple event handler is a function that extracts the
  2605. pertinent data from the Apple event, performs the action requested by the Apple
  2606. event, and returns a result. For example, if the event has an event class of
  2607. kCoreEventClass and an event ID of kAEOpenDocuments, the AEProcessAppleEvent
  2608. function calls your application’s routine for handling the Open Documents event.
  2609.  
  2610. You install Apple event handlers by using the AEInstallEventHandler function.
  2611. This function creates an Apple event dispatch table that the Apple Event Manager
  2612. uses to map Apple events to handlers in your application. After being called by
  2613. the AEProcessAppleEvent function to process an Apple event, the Apple Event
  2614. Manager reads the Apple event dispatch table and, if your application has
  2615. installed a handler for that Apple event, calls your handler to finish
  2616. responding to the event. Figure 6-8 shows how the flow of control passes from
  2617. your application to the Apple Event Manager and back to your application.
  2618.  
  2619. ¿ Figure 6-8   The Apple Event Manager calling the handler for an Open Documents
  2620. event ø 
  2621.  
  2622. Your Apple event handlers must generally perform the following tasks:
  2623.  
  2624.   • extract the parameters and attributes for the Apple event
  2625.  
  2626.   • check that all the required parameters have been extracted
  2627.  
  2628.   • set user interaction level preferences if necessary and, if your application
  2629.   needs 
  2630.      to interact with the user, use the AEInteractWithUser function to bring it
  2631.      to the
  2632.      foreground
  2633.  
  2634.   • perform the action requested by the Apple event
  2635.  
  2636.   • dispose of any copies of descriptor records that have been created
  2637.  
  2638.   • return a result for the client
  2639.  
  2640. You must use Apple Event Manager functions to extract the data from Apple
  2641. events. You can also use Apple Event Manager functions to get data out of
  2642. descriptor records, descriptor lists, and AE records. Most of these routines are
  2643. available in two forms: one that uses a buffer to return a copy of the desired
  2644. data and one that returns a copy of the descriptor record containing the data.
  2645. The following list shows the main functions you can use to access the data of an
  2646. Apple event.
  2647.  
  2648. Function                                Description
  2649.  
  2650. AEGetParamPtr                    Uses a buffer to return the data contained in a
  2651.                                                  parameter; used, for example,
  2652.                                                  to extract the result code
  2653.                                                  from the keyErrorNumber
  2654.                                                  parameter of a reply Apple
  2655.                                                  event.
  2656.  
  2657. AEGetParamDesc                 Returns the descriptor record or descriptor list
  2658. for a
  2659.                                                  parameter; used, for example,
  2660.                                                  to extract the descriptor
  2661.                                                  list for a list of alias
  2662.                                                  records specified in the direct
  2663.                                                  parameter of the Open Documents
  2664.                                                  event.
  2665.  
  2666. AEGetAttributePtr               Uses a buffer to return the data contained in an
  2667. attribute;
  2668.                                                  used, for example, to determine
  2669.                                                  the source of an Apple
  2670.                                                  event by extracting the data
  2671.                                                  from the
  2672.                                                  keyEventSourceAttr attribute.
  2673.  
  2674. AEGetAttributeDesc            Returns the descriptor record for a parameter;
  2675. used, for
  2676.                                                   example, to make a copy of a
  2677.                                                   descriptor record
  2678.                                                   containing the address of an
  2679.                                                   application.
  2680.  
  2681. AECountItems                     Returns the number of descriptor records in a
  2682. descriptor
  2683.                                                  list; used, for example, to
  2684.                                                  determine the number of alias
  2685.                                                  records for documents specified
  2686.                                                  in the direct parameter
  2687.                                                  of the Open Documents event.
  2688.  
  2689. AEGetNthPtr                       Uses a buffer to return the data for a
  2690. descriptor record
  2691.                                                 that is contained in a
  2692.                                                 descriptor list; used, for
  2693.                                                 example, to
  2694.                                                 extract a document’s alias
  2695.                                                 record from the descriptor list
  2696.                                                 specified in the direct
  2697.                                                 parameter of the Open Documents
  2698.                                                 event.
  2699.  
  2700. AEGetNthDesc                   Returns a descriptor record from a descriptor
  2701. list; used,
  2702.                                                for example, to get the
  2703.                                                descriptor record containing an
  2704.                                                alias record from the list
  2705.                                                specified in the direct parameter
  2706.                                                of the Open Documents event.
  2707.  
  2708. You can specify the descriptor type of the resulting data for these functions;
  2709. if this is different from the descriptor type of the attribute or parameter, the
  2710. Apple Event Manager attempts to coerce it to the specified type. In the direct
  2711. parameter of the Open Documents event, for example, each descriptor record in
  2712. the descriptor list is an alias record; each alias record specifies a document
  2713. to be opened. As explained in the File Manager chapter of this volume, all your
  2714. application usually needs is the file system specification (FSSpec) record of
  2715. the document. When you extract the descriptor from the descriptor list, you can
  2716. request that the Apple Event Manager return the data to your application as a
  2717. file system specification record instead of as an alias record.
  2718.  
  2719. After extracting all known parameters, your handler should check that it
  2720. retrieved all the required parameters by checking whether the
  2721. keyMissedKeywordAttr attribute exists. If the attribute exists, then your
  2722. handler has not retrieved all the required parameters, and it should return an
  2723. error.
  2724.  
  2725. In some cases, the server may need to interact with the user when it handles an
  2726. Apple event. For example, your handler for the Print Documents event may need to
  2727. display a print options dialog box and get settings from the user before
  2728. printing. Your handler should always use the AEInteractWithUser function before
  2729. displaying a dialog box or alert box or otherwise interacting with the user. By
  2730. specifying one of these flags to the AESetInteractionAllowed function, you can
  2731. set your application’s user interaction level preferences.
  2732.  
  2733. Flag                                           Description
  2734.  
  2735. kAEInteractWithSelf            User interaction with your server application in
  2736.                                                    response to an Apple event
  2737.                                                    may be allowed only when
  2738.                                                    the client application is
  2739.                                                    your own application—that is,
  2740.                                                    only when your application is
  2741.                                                    sending the Apple event
  2742.                                                    to itself.
  2743.  
  2744. kAEInteractWithLocal         User interaction with your server application in
  2745.                                                    response to an Apple event
  2746.                                                    may be allowed only if the
  2747.                                                    client application is on the
  2748.                                                    same computer as your
  2749.                                                    application; this is the
  2750.                                                    default if the
  2751.                                                    AESetInteractionAllowed
  2752.                                                    function is not used.
  2753.  
  2754. kAEInteractWithAll             User interaction with your server application in
  2755.                                                     response to an Apple event
  2756.                                                     may be allowed for any
  2757.                                                     client application on any
  2758.                                                     computer.
  2759.  
  2760. For a server application to allow user interaction in response to the client’s
  2761. Apple event, two conditions must be met. First, the client application must
  2762. request that your server application allow user interaction. Second, your server
  2763. application must allow user interaction in response to the Apple event sent from
  2764. that client application as described in the previous list. If these conditions
  2765. are met and your application needs to interact with the user, the
  2766. AEInteractWithUser function brings your application to the foreground if it
  2767. isn’t already in the foreground. Your application can then display its dialog
  2768. box or alert box or otherwise interact with the user. AEInteractWithUser brings
  2769. your server application to the front either directly or after the user responds
  2770. to a notification request.
  2771.  
  2772. When your application acts on an Apple event, it should perform the standard
  2773. action requested by that event. For example, if the Apple event is the Open
  2774. Documents event, your application should open the specified documents in titled
  2775. windows just as if the user had selected each document from the Finder and then
  2776. chosen Open from the File menu. You should strive to create routines that can be
  2777. called in response to both user events and Apple events. To do this, you need to
  2778. isolate code for interacting with the user from the code that performs the
  2779. requested action—such as opening a document. You then call the code that
  2780. performs the requested action from your Apple event handler.
  2781.  
  2782. When you extract a descriptor record by using the AEGetParamDesc,
  2783. AEGetAttributeDesc, AEGetNthDesc, or AEGetKeyDesc functions, the Apple Event
  2784. Manager creates a copy of the descriptor record for you to use. When your
  2785. handler is finished using a copy of a descriptor record, you should dispose of
  2786. it—and thereby deallocate the memory it uses—by calling the AEDisposeDesc
  2787. function.
  2788.  
  2789. The required Apple events ask your application to perform tasks—open your
  2790. application, open or print documents, or quit your application. Other Apple
  2791. events may ask your application to return data. For example, if your application
  2792. is a spelling checker, the client probably expects data in the form of a list of
  2793. misspelled words to be returned from your application. If a reply is requested,
  2794. the Apple Event Manager prepares a reply Apple event for the client by passing a
  2795. default reply Apple event to your handler. The default reply Apple event has no
  2796. parameters when it is passed to your handler. Your handler can add any
  2797. parameters to the reply Apple event. If your application is a spelling checker,
  2798. for example, you can return a list of misspelled words in a parameter.
  2799.  
  2800. Your handler routine should always set its function result either to noErr if it
  2801. successfully handles the Apple event or to a nonzero result code if an error
  2802. occurs. If an error occurs, the Apple Event Manager adds a keyErrorNumber
  2803. parameter to the reply Apple event; this parameter contains the result code that
  2804. your handler returns. The client should check whether the keyErrorNumber
  2805. parameter exists to determine whether your handler performed the requested
  2806. action. In addition to returning a result code, your handler can also return an
  2807. error string in the keyErrorString parameter of the reply Apple event. The
  2808. client can use this string in an error message to the user.
  2809.  
  2810. If the source requested a reply, the Apple Event Manager returns the reply Apple
  2811. event to the source. The reply Apple event is identified by the event class
  2812. kCoreEventClass and by the event ID kAEAnswer. When you have finished using the
  2813. reply Apple event, you should dispose of it—and thereby deallocate the memory it
  2814. uses—by calling the AEDisposeDesc function.
  2815.  
  2816. When your handler returns a result code to the Apple Event Manager, you have
  2817. finished your response to the client’s Apple event. Figure 6-9 shows the entire
  2818. process of responding to an Apple event. The next section describes how to send
  2819. an Apple event.
  2820.  
  2821. ¿ Figure 6-9   Responding to an Open Documents eventi.Open Documents event ø 
  2822.  
  2823. _______________________________________________________________________________
  2824.  
  2825. æKY Requesting…Services…Through…Apple…Events
  2826. æC »Requesting Services Through Apple Events                       The Apple Event Manager
  2827. _______________________________________________________________________________
  2828.  
  2829. Your application can use Apple events to request services from other
  2830. applications. By using Finder events, for example, your application can simulate
  2831. the behavior of the Finder by requesting that the Finder perform such operations
  2832. as launching an application on your behalf. By using functional-area Apple
  2833. events, your application can request services from applications related to your
  2834. own—for example, asking a spelling checker application to check the text in a
  2835. document created by your application. All publicly available Apple events are
  2836. defined and published in the Apple Event Registry.  Consult the Apple Event
  2837. Registry  for the format and function of Apple events that your application may
  2838. wish to send.
  2839.  
  2840. The previous section describes how a server application responds to a client
  2841. application’s request for services. This section briefly describes the steps
  2842. your application must take to act as a client application and request such
  2843. services. To request a service through an Apple event, your application must
  2844.  
  2845.   • create an Apple event by calling the AECreateAppleEvent function
  2846.  
  2847.   • use Apple Event Manager functions to add parameters and any other necessary 
  2848.      attributes to the Apple event
  2849.  
  2850.   • call the AESend function to send the Apple event
  2851.  
  2852.   • dispose of any copies of descriptor records that you have created
  2853.  
  2854.   • process the reply Apple event (optional)
  2855.  
  2856. Use the AECreateAppleEvent function to create an Apple event record. Using the
  2857. arguments you pass to the AECreateAppleEvent function, the Apple Event Manager
  2858. constructs the data structures describing the event class, the event ID, and the
  2859. target address attributes of an Apple event. The event class and event ID, of
  2860. course, identify the particular event you wish to send. The target address
  2861. identifies the application to which you wish to send the Apple event.
  2862.  
  2863. To act as a server application for your application, the target must support
  2864. high-level events and must be open. The server can be your own application,
  2865. another application running on the user’s computer, or an application running on
  2866. another user’s computer connected to the network. Your application should offer
  2867. some facility to launch a server application if it is not already running. It is
  2868. recommended that you use the Open Selection event (identified by the event class
  2869. kAEFinderEvents and the event ID kAEOpenSelection) to request that the Finder
  2870. launch applications; however, the Process Manager also provides a means for your
  2871. application to launch other applications. See the Apple Event Registry  for
  2872. information on Finder events, and see the Process Management chapter in this
  2873. volume for information on using the Process Manager.
  2874.  
  2875. Your application should also offer a facility to allow the user to choose among
  2876. the various applications available as servers. The PPCBrowser function allows
  2877. users to select target applications on the user’s computer as well as those
  2878. available on computers connected to the network.  The PPCBrowser function
  2879. presents a standard user interface for choosing a target application, much as
  2880. the Standard File Package provides a standard user interface for opening and
  2881. saving files. See the Program-to-Program Communications Toolbox chapter of this
  2882. volume for details on using the PPCBrowser function.
  2883.  
  2884. If the server application is on a remote computer on a network, the user of that
  2885. computer must allow program linking to the server application. The user of the
  2886. server application does this by selecting the application from the Finder and
  2887. choosing Sharing from the File menu and then clicking the Allow Remote Program
  2888. Linking checkbox. If the user has not yet started program linking, the Sharing
  2889. command offers to display the Sharing Setup control panel so that the user can
  2890. start program linking. The user must also authorize remote users for program
  2891. linking by using the Users and Groups control panel. Program linking and setting
  2892. up authenticated sessions are described in the Program-to-Program Communications
  2893. chapter in this volume.
  2894.  
  2895. There are two other attributes you specify in the AECreateAppleEvent function:
  2896. the reply ID and the transaction ID. For the reply ID attribute, you’ll usually
  2897. specify the kAutoGenerateReturnID constant to the AECreateAppleEvent function.
  2898. This ensures that the Apple Event Manager generates a unique return ID for the
  2899. reply Apple event returned from the server. For the transaction ID attribute,
  2900. you’ll usually specify the kAnyTransactionID constant, which indicates that this
  2901. Apple event is not one of a series of interdependent Apple events.
  2902.  
  2903. The Apple event record created with the AECreateAppleEvent function serves as a
  2904. template for the Apple event you want to send. To add the remaining attributes
  2905. and parameters necessary for your Apple event, you must use these additional
  2906. Apple Event Manager functions.
  2907.  
  2908. Function                             Description
  2909.  
  2910. AEPutParamPtr                 Takes a keyword, descriptor type, and a pointer to
  2911. data,
  2912.                                                converts them into a parameter,
  2913.                                                and adds the parameter
  2914.                                                to or replaces it in an Apple
  2915.                                                event record; used, for
  2916.                                                example, to place numbers into
  2917.                                                the parameters of an
  2918.                                                Apple event requesting that the
  2919.                                                server perform a
  2920.                                                calculation.
  2921.  
  2922. AEPutParamDesc               Takes a keyword and a descriptor record, converts
  2923. them
  2924.                                                 into a parameter, and adds the
  2925.                                                 parameter to or replaces it
  2926.                                                 in an Apple event record; used,
  2927.                                                 for example, to place a
  2928.                                                 descriptor list containing alias
  2929.                                                 records into the direct
  2930.                                                 parameter of an Apple event that
  2931.                                                 requests a server to
  2932.                                                 manipulate files.
  2933.  
  2934. AEPutAttributePtr             Takes a keyword, descriptor type, and a pointer to
  2935. data,
  2936.                                                 converts them into an attribute,
  2937.                                                 and adds the attribute to
  2938.                                                 or replaces it in an Apple event
  2939.                                                 record; used, for
  2940.                                                 example, to change the event ID
  2941.                                                 of an Apple event
  2942.                                                 record that is waiting to be
  2943.                                                 sent.
  2944.  
  2945. AEPutAttributeDesc          Takes a keyword and a descriptor record, converts
  2946. them
  2947.                                                 into an attribute, and adds the
  2948.                                                 attribute to or replaces it in
  2949.                                                 an Apple event record; used, for
  2950.                                                 example, to replace the
  2951.                                                 descriptor record used for the
  2952.                                                 target address attribute in
  2953.                                                 an Apple event record waiting to
  2954.                                                 be sent.
  2955.  
  2956. Descriptor records and descriptor lists are the basic components from which an
  2957. Apple event record is constructed; these are passed to the AEPutParamDesc and
  2958. AEPutAttributeDesc functions. Use the following functions to create descriptor
  2959. records and descriptor lists.
  2960.  
  2961. Function                             Description
  2962.  
  2963. AECreateDesc                     Takes a descriptor type and a pointer to data
  2964. and converts
  2965.                                                them into a descriptor record;
  2966.                                                used, for example, to create
  2967.                                                a descriptor record that is used
  2968.                                                as an attribute or a
  2969.                                                parameter in an Apple event
  2970.                                                record.
  2971.  
  2972. AEPutPtr                              Takes a descriptor type and a pointer to
  2973. data, converts
  2974.                                                 them into a descriptor record,
  2975.                                                 and adds the record to a
  2976.                                                 descriptor list; used, for
  2977.                                                 example, to place into a
  2978.                                                 descriptor list a number that is
  2979.                                                 used as the parameter of
  2980.                                                 an Apple event requesting a
  2981.                                                 calculation.
  2982.  
  2983. AEPutDesc                            Adds a descriptor record to a descriptor
  2984. list; used, for
  2985.                                                  example, to add into the
  2986.                                                  descriptor list an alias record
  2987.                                                  that is used as the direct
  2988.                                                  parameter of an Apple event
  2989.                                                  requesting file manipulation.
  2990.  
  2991. After you add all the attributes and parameters required for the Apple event,
  2992. use the AESend function to send the Apple event. The Apple Event Manager uses
  2993. the Event Manager to transmit the Apple event to the server application.
  2994.  
  2995. The AESend function requires that you specify whether and how your application
  2996. should wait for a reply from the server. When the server receives your Apple
  2997. event, the Apple Event Manager prepares a reply Apple event for your application
  2998. by passing a default reply Apple event to the server. The Apple Event Manager
  2999. returns any nonzero result code from the server’s handler in the keyErrorNumber
  3000. parameter of the reply Apple event. If your application wants to return an error
  3001. string, add it to the reply Apple event in the keyErrorString parameter. The
  3002. server can also use this reply Apple event to return any data you requested—for
  3003. example, the results of a numerical calculation or a list of misspelled words.
  3004.  
  3005. You specify how your application should wait for a reply by using one of these
  3006. flags in the sendMode parameter of the AESend function.
  3007.  
  3008. Flag                                 Description
  3009.  
  3010. kAENoReply                 Your application does not want a reply Apple event;
  3011. the
  3012.                                            server processes your Apple event as
  3013.                                            soon as it has the 
  3014.                                            opportunity.
  3015.  
  3016. kAEQueueReply           Your application wants a reply Apple event; the reply
  3017.                                            appears in your event queue as soon
  3018.                                            as the server has the
  3019.                                            opportunity to process and respond to
  3020.                                            your Apple event.
  3021.  
  3022. kAEWaitReply              Your application wants a reply Apple event and is
  3023. willing to
  3024.                                           give up the processor while waiting
  3025.                                           for the reply; for
  3026.                                           example, if the server application is
  3027.                                           on the same computer
  3028.                                           as your application, your application
  3029.                                           yields the processor to
  3030.                                           allow the server to respond to your
  3031.                                           Apple event.
  3032.  
  3033. If you specify the kAEWaitReply flag, you may provide an idle function. This
  3034. function should process any events that occur while your application is waiting
  3035. for a reply. You supply a pointer to your idle function as a parameter to the
  3036. AESend function. So that your application can process other Apple events while
  3037. it is waiting for a reply, you can also specify an optional filter function to
  3038. the AESend function that filters Apple events.
  3039.  
  3040. If your Apple event may require the user to interact with the server application
  3041. (for example, to specify print or file options), you can communicate your
  3042. user-interaction preferences to the server by specifying one of the following
  3043. flags in the sendMode parameter of the AESend function.
  3044.  
  3045. Flag                                 Description
  3046.  
  3047. kAENeverInteract       The server application should never interact with the
  3048. user
  3049.                                           in response to this Apple event. If
  3050.                                           this flag is set,
  3051.                                           AEInteractWithUser does not bring the
  3052.                                           server application to
  3053.                                           the foreground (this is the default
  3054.                                           when an Apple event is
  3055.                                           sent to a remote application).
  3056.  
  3057. kAECanInteract            The server application can interact with the user in
  3058. response
  3059.                                           to this Apple event—by convention, if
  3060.                                           the user needs to 
  3061.                                           supply information to the server. If
  3062.                                           this flag is set and the
  3063.                                           server allows interaction,
  3064.                                           AEInteractWithUser brings the 
  3065.                                           server application to the foreground
  3066.                                           (this is the default 
  3067.                                           when an Apple event is sent to a local
  3068.                                           application).
  3069.  
  3070. kAEAlwaysInteract       The server application can interact with the user in 
  3071.                                            response to this Apple event—by
  3072.                                            convention, even if no 
  3073.                                            information is needed from the user.
  3074.                                            If this flag is set and 
  3075.                                            the server allows interaction,
  3076.                                            AEInteractWithUser brings 
  3077.                                            the server application to the
  3078.                                            foreground. The Apple Event
  3079.                                            Manager does not distinguish between
  3080.                                            this flag and the
  3081.                                            kAECanInteract flag—distinguishing
  3082.                                            between them is the
  3083.                                            responsibility of the server
  3084.                                            application.
  3085.  
  3086. kAECanSwitchLayer     If both the client and server allow interaction and this
  3087. flag
  3088.                                             is set, AEInteractWithUser brings
  3089.                                             the server directly to the 
  3090.                                             foreground if adherence to the
  3091.                                             principle of user control 
  3092.                                             allows. If the action would be
  3093.                                             contrary to this principle, 
  3094.                                             AEInteractWithUser uses the
  3095.                                             Notification Manager to 
  3096.                                             request that user bring the server
  3097.                                             application to the 
  3098.                                             foreground. If both the client and
  3099.                                             server allow interaction 
  3100.                                             and this flag is not set,
  3101.                                             AEInteractWithUser always uses the
  3102.                                             Notification Manager to request that
  3103.                                             the user bring the 
  3104.                                             server application to the
  3105.                                             foreground.
  3106.  
  3107. The server can set its own interaction preferences. The interaction of your
  3108. client’s preferences and the server’s is explained in “Interacting With the
  3109. User” later in this chapter.
  3110.  
  3111. After you send an Apple event, your application is responsible for disposing of
  3112. the Apple event record—and thereby deallocating the memory it uses—by calling
  3113. the AEDisposeDesc function. If you create one descriptor record and add it to
  3114. another, the Apple Event Manager creates a copy of the newly created one and
  3115. adds that copy to the existing one. For example, you might use the AECreateDesc
  3116. function to create a descriptor record that you wish to add to an Apple event.
  3117. When you use the AEPutParamDesc function, it creates a copy of your newly
  3118. created descriptor record and adds that copy as a parameter to an existing Apple
  3119. event.
  3120.  
  3121. Your application should dispose of all the descriptor records that are created
  3122. in order to add parameters and attributes to an Apple event. You normally
  3123. dispose of your Apple event and its reply after you receive a result from the
  3124. AESend function. You should dispose of these even if AESend returns an error
  3125. result. If your application requests a reply Apple event, your application must
  3126. also dispose of the reply Apple event when finished processing it.
  3127.  
  3128. Your application can request a reply Apple event. If you specify the
  3129. kAEWaitReply flag, the reply Apple event is returned in a parameter you pass to
  3130. the AESend function. If you specify the kAEQueueReply flag to the AESend
  3131. function, the reply Apple event is returned in the event queue. In this case,
  3132. the reply is identified by the event class kCoreEventClass and the event ID
  3133. kAEAnswer; your application processes reply events that it receives in its event
  3134. queue in the same manner that server applications process Apple events, as
  3135. described earlier in “Responding to Apple Events.” 
  3136.  
  3137. Your application should check for the keyErrorNumber parameter of the reply
  3138. Apple event to ensure that the server performed the requested action. Any error
  3139. messages that the server returns for you to display to your user will appear in
  3140. the keyErrorString parameter.
  3141.  
  3142. When your handler is finished using a copy of a descriptor record used in the
  3143. reply Apple event, you should dispose of them both—and thereby deallocate the
  3144. memory they use—by calling the AEDisposeDesc function.
  3145.  
  3146. The next section, “Using the Apple Event Manager,” describes in greater detail
  3147. the routines necessary for sending and responding to Apple events.
  3148.  
  3149. _______________________________________________________________________________
  3150.  
  3151. æKY Using…the…Apple…Event…Manager…Volume…VI
  3152. æC »Using the Apple Event Manager Volume VI                        The Apple Event Manager
  3153. _______________________________________________________________________________
  3154.  
  3155. The following sections explain in more detail how to use the Apple Event Manager
  3156. to receive, accept, and send Apple events. The first two sections describe how
  3157. to accept and process Apple events and how to install entries into the Apple
  3158. event dispatch table. The following section fully explains how your application
  3159. should handle the required Apple events, and it provides code that shows sample
  3160. handlers for the required Apple events.
  3161.  
  3162. Additional sections describe how to
  3163.  
  3164.   • handle events that support publish and subscribe features
  3165.  
  3166.   • get data out of an Apple event
  3167.  
  3168.   • write handlers that perform the action requested by an Apple event
  3169.  
  3170.   • reply to an Apple event
  3171.  
  3172.   • dispose of Apple event data structures
  3173.  
  3174.   • interact with the user when processing an Apple event
  3175.  
  3176.   • create an Apple event
  3177.  
  3178.   • send an Apple event
  3179.  
  3180.   • write an idle function
  3181.  
  3182.   • write a reply filter function
  3183.  
  3184.   • write and install coercion handlers
  3185.  
  3186.   • use the Application Died event to ascertain the termination of an
  3187.   application 
  3188.      that has been launched by your application
  3189.  
  3190. The Apple Event Manager is available only in system software version 7.0. Use
  3191. the Gestalt function with the gestaltAppleEventsAttr selector to determine
  3192. whether the Apple Event Manager is available. In the response parameter, the bit
  3193. defined by the constant gestaltAppleEventsPresent is set if the Apple Event
  3194. Manager is available.     
  3195.  
  3196.    CONST  gestaltAppleEventsAttr    = 'evnt';  {Gestalt selector}
  3197.           gestaltAppleEventsPresent = 0;       {if this bit is set, then }
  3198.                                                {Apple Event Mgr’s available}
  3199. _______________________________________________________________________________
  3200.  
  3201. æKY Accepting…an…Apple…Event
  3202. æC »Accepting an Apple Event                                       The Apple Event Manager
  3203. _______________________________________________________________________________
  3204.  
  3205. To accept Apple events (or any other high-level events), you must set the
  3206. appropriate flags in your application’s 'SIZE' resource and include code to
  3207. handle high-level events in your application’s main event loop. 
  3208.  
  3209. Two flags in the 'SIZE' resource determine whether an application receives
  3210. high-level events: 
  3211.  
  3212.   • The isHighLevelEventAware flag must be set for your application to receive
  3213.   any
  3214.      high-level events.
  3215.  
  3216.   • The localAndRemoteHLEvents flag must be set for your application to receive 
  3217.      high-level events sent from another computer on the network.
  3218.  
  3219. Note that in order for your application to respond to Apple events sent from
  3220. remote computers, the user of your application must also allow network users to
  3221. link to your application. The user does this by selecting your application from
  3222. the Finder and choosing Sharing from the File menu and then clicking the Allow
  3223. Remote Program Linking checkbox. If the user has not yet started program
  3224. linking, the Sharing command offers to display the Sharing Setup control panel
  3225. so that the user can start program linking. The user must also authorize remote
  3226. users for program linking by using the Users and Groups control panel. Program
  3227. linking and setting up authenticated sessions are described in the
  3228. Program-to-Program Communications chapter in this volume.
  3229.  
  3230. For a complete description of the 'SIZE' resource, see the Event Manager chapter
  3231. in this volume.
  3232.  
  3233. Apple events (and other high-level events) are identified by a message class of
  3234. kHighLevelEvent in the what field of the event record. You can test the what
  3235. field of the event record to determine whether the event is a high-level event.
  3236.  
  3237. Listing 6-1 is an example of a procedure called from an application’s main event
  3238. loop that handles events, including high-level events. The procedure determines
  3239. the type of event received and then calls another routine to take the
  3240. appropriate action.
  3241.  
  3242. ¿ Listing 6-1   A DoEvent procedure
  3243.  
  3244. PROCEDURE DoEvent (event: EventRecord);
  3245.  
  3246. BEGIN              
  3247.     CASE event.what OF      {determine the type of event}
  3248.        mouseDown:
  3249.           DoMouseDown (event);
  3250.        .
  3251.        . {handle other kinds of events}
  3252.        .
  3253.        {handle high-level events, including Apple events}
  3254.        kHighLevelEvent:
  3255.           DoHighLevelEvent (event);
  3256.      END;
  3257. END; 
  3258.  
  3259. Listing 6-2 is an example of a DoHighLevelEvent procedure that handles Apple
  3260. events and also handles the high-level event identified by the event class
  3261. mySpecialHLEventClass and the event ID mySpecialHLEventID. Note that, in most
  3262. cases, you should use Apple events to communicate with other applications. 
  3263.  
  3264. ¿ Listing 6-2   A DoHighLevelEvent procedure for handling Apple events and other
  3265. high-level events
  3266.  
  3267. PROCEDURE DoHighLevelEvent (event: EventRecord);
  3268.  
  3269. VAR
  3270.    myErr : OSErr;
  3271. BEGIN
  3272.    IF event.message = LongInt(mySpecialHLEventClass) AND
  3273.       event.where = LongInt(mySpecialHLEventID) THEN
  3274.    BEGIN
  3275.    {it's a high-level event that doesn't use AEIMP}
  3276.       myErr := HandleMySpecialHLEvent(event);
  3277.       IF myErr <> noErr THEN
  3278.          DoError(myErr);  {perform the necessary error handling}
  3279.    END;
  3280.    ELSE    {otherwise, assume that the event is an Apple event}
  3281.    BEGIN
  3282.       myErr := AEProcessAppleEvent(event);
  3283.       IF myErr <> noErr THEN
  3284.          DoError(myErr);
  3285.    END;
  3286. END;
  3287.  
  3288. If your application accepts high-level events that do not follow the Apple Event
  3289. Interprocess Messaging Protocol (AEIMP), you must dispatch these high-level
  3290. events before calling AEProcessAppleEvent. To dispatch a high-level event that
  3291. does not follow AEIMP, for each event you should check the event class, the
  3292. event ID, or both to see if the event is one that your application can handle. 
  3293.  
  3294. After receiving a high-level event (and, if appropriate, checking whether it is
  3295. a type of high-level event other than an Apple event), your application
  3296. typically calls the AEProcessAppleEvent function. The AEProcessAppleEvent
  3297. function determines the type of Apple event received, gets the event buffer that
  3298. contains the parameters and attributes of the Apple event, and calls the
  3299. corresponding Apple event handler routine in your application.
  3300.  
  3301. You should provide a handler routine for each Apple event that your application
  3302. supports. Your handler routine for a particular Apple event is responsible for
  3303. performing the action requested by the Apple event, and your handler can
  3304. optionally return data in the reply Apple event. 
  3305.  
  3306. After your handler finishes processing the Apple event and adds any parameters
  3307. to the default reply, it should return a result code to AEProcessAppleEvent. If
  3308. the client application is waiting for a reply, the Apple Event Manager returns
  3309. the reply Apple event to the client.
  3310.  
  3311. _______________________________________________________________________________
  3312.  
  3313. æKY Installing…Entries…Into…the…Apple…Event…Dispatch…Tables
  3314. æC »Installing Entries Into the Apple Event Dispatch Tables        The Apple Event Manager
  3315. _______________________________________________________________________________
  3316.  
  3317. When your application receives an Apple event, use the AEProcessAppleEvent
  3318. function to retrieve the data buffer of the event and to route the Apple event
  3319. to the appropriate Apple event handler in your application. Your application
  3320. supplies an Apple event dispatch table to provide a mapping between the Apple
  3321. events your application supports and the Apple event handlers provided by your
  3322. application.
  3323.  
  3324. To install entries into your application’s Apple event dispatch table, use the
  3325. AEInstallEventHandler function. You usually install entries for all of the Apple
  3326. events that your application accepts into your application’s Apple event
  3327. dispatch table. 
  3328.  
  3329. For each Apple event your application supports, you should install entries in
  3330. your Apple event dispatch table that specify
  3331.  
  3332.   • the event class of the Apple event
  3333.  
  3334.   • the event ID of the Apple event
  3335.  
  3336.   • the address of the Apple event handler for the Apple event
  3337.  
  3338.   • a reference constant
  3339.  
  3340. You provide this information to the AEInstallEventHandler function. In addition,
  3341. you indicate to the AEInstallEventHandler function whether the entry should be
  3342. added to your application’s Apple event dispatch table or the system Apple event
  3343. dispatch table.
  3344.  
  3345. The system Apple event dispatch table is a table in the system heap that
  3346. contains handlers that are available to all applications and processes running
  3347. on the same computer. The handlers in your application’s Apple event dispatch
  3348. table are available only to your application. If AEProcessAppleEvent cannot find
  3349. a handler for the Apple event in your application’s Apple event dispatch table,
  3350. it looks in the system Apple event dispatch table for a handler. If it doesn’t
  3351. find a handler there either, it returns the errAEEventNotHandled result code.
  3352.  
  3353.  Listing 6-3 illustrates how to add entries for the required Apple events to
  3354.  your application’s Apple event dispatch table.
  3355.  
  3356. ¿ Listing 6-3   Inserting entries for required Apple events into an
  3357. application’s Apple event dispatch table
  3358.  
  3359. myErr := AEInstallEventHandler (kCoreEventClass, kAEOpenApplication, 
  3360.                                 @MyOAPP, 0, FALSE);
  3361. IF myErr <> noErr THEN DoError(myErr);
  3362. myErr := AEInstallEventHandler (kCoreEventClass, kAEOpenDocuments, 
  3363.                                 @MyODOC, 0, FALSE);
  3364. IF myErr <> noErr THEN DoError(myErr);
  3365. myErr := AEInstallEventHandler (kCoreEventClass, kAEPrintDocuments, 
  3366.                                 @MyPDOC, 0, FALSE);
  3367. IF myErr <> noErr THEN DoError(myErr);
  3368. myErr := AEInstallEventHandler (kCoreEventClass, kAEQuitApplication, 
  3369.                                 @MyQUIT, 0, FALSE); 
  3370. IF myErr <> noErr THEN DoError(myErr);    
  3371.  
  3372. The code in Listing 6-3 creates an entry for all required Apple events in the
  3373. Apple event dispatch table. The first entry creates an entry for the Open
  3374. Application event. The entry indicates the event class and event ID of the Open
  3375. Application event, the address of the handler for that event, and specifies 0 as
  3376. the reference constant. This entry is installed into the application’s Apple
  3377. event dispatch table.
  3378.  
  3379. The reference constant is passed to your handler by the Apple Event Manager each
  3380. time your handler is called. Your application can use this reference constant
  3381. for any purpose. If your application doesn’t use the reference constant, use 0
  3382. as the value. 
  3383.  
  3384. The last parameter to the AEInstallEventHandler function is a Boolean value that
  3385. determines whether the entry is added to the system Apple event dispatch table
  3386. or to your application’s Apple event dispatch table. To add the entry to your
  3387. application’s dispatch table, use FALSE as the value of this parameter. If you
  3388. specify TRUE, the entry is added to the system’s Apple event dispatch table.
  3389.  
  3390. If you add a handler to the system Apple event dispatch table, the handler that
  3391. you specify must reside in the system heap.
  3392.  
  3393.    Note: When an application calls a system Apple event handler, the A5 register
  3394.    is
  3395.    set up for the calling application. For this reason, if you provide a system
  3396.    Apple 
  3397.    event handler, it should never use A5 global variables or anything that
  3398.    depends 
  3399.    on a particular context; otherwise, the application that calls the system
  3400.    handler 
  3401.    may crash.
  3402.  
  3403. For any entry in your Apple event dispatch table, you can specify a wildcard
  3404. value for the event class, event ID, or both. You specify a wildcard by
  3405. supplying the typeWildCard constant when installing an entry into the Apple
  3406. event dispatch table. A wildcard value matches all possible values. 
  3407.  
  3408. For example, if you specify an entry with the typeWildCard event class and the
  3409. kAEOpenDocuments event ID, the Apple Event Manager dispatches Apple events of
  3410. any event class and an  event ID of kAEOpenDocuments to the handler for that
  3411. entry. 
  3412.  
  3413. If you specify an entry with the kCoreEventClass event class and the
  3414. typeWildCard event ID, the Apple Event Manager dispatches Apple events of the
  3415. kCoreEventClass event class and any event ID to the handler for that entry. 
  3416.  
  3417. If you specify an entry with the typeWildCard event class and the typeWildCard
  3418. event ID, the Apple Event Manager dispatches all Apple events of any event class
  3419. and any event ID to the handler for that entry.
  3420.  
  3421. If the AEProcessAppleEvent function cannot find a handler for an Apple event in
  3422. either the application’s Apple event dispatch table or the system Apple event
  3423. dispatch table, it returns the result code errAEEventNotHandled to the Apple
  3424. event server. If the client is waiting for a reply, AESend also returns this
  3425. result code as its function result.
  3426.  
  3427. If your application supports the Edition Manager, you should also add entries to
  3428. your application’s Apple event dispatch table for the Apple events that your
  3429. application receives from the Edition Manager. Listing 6-4 shows how to add
  3430. entries for these Apple events to your application’s Apple event dispatch table.
  3431.  
  3432. ¿ Listing 6-4   Inserting entries for Apple events sent by the Edition Manager
  3433. into an application’s Apple event dispatch table
  3434.  
  3435. myErr := AEInstallEventHandler(sectionEventMsgClass, sectionReadMsgID, 
  3436.                                @MyHandleSectionReadEvent, 0, FALSE);
  3437. IF myErr <> noErr THEN DoError(myErr);
  3438. myErr := AEInstallEventHandler(sectionEventMsgClass, 
  3439.                                sectionWriteMsgID, 
  3440.                                @MyHandleSectionWriteEvent, 0, FALSE);
  3441. IF myErr <> noErr THEN DoError(myErr);
  3442. myErr := AEInstallEventHandler(sectionEventMsgClass, 
  3443.                                sectionScrollMsgID, 
  3444.                                @MyHandleSectionScrollEvent, 0, FALSE);
  3445. IF myErr <> noErr THEN DoError(myErr);
  3446.  
  3447. See “Handling Apple Events Sent by the Edition Manager” later in this chapter
  3448. for the parameters associated with these events. See the Edition Manager chapter
  3449. in this volume for information on how your application should respond to the
  3450. Apple events sent by the Edition Manager.
  3451. _______________________________________________________________________________
  3452.  
  3453. æKY Handling…the…Required…Apple…Events
  3454. æC »Handling the Required Apple Events                             The Apple Event Manager
  3455. _______________________________________________________________________________
  3456.  
  3457. This section describes the required Apple events—the Apple events your
  3458. application must support to be 7.0-friendly—and the descriptor types for all
  3459. parameters of the required Apple events. It also describes how to write the
  3460. handlers for these events, and it provides sample code.
  3461.  
  3462. To support the required Apple events, you must set the necessary flags in the
  3463. 'SIZE' resource of your application, install entries into your application’s
  3464. Apple event dispatch table, add code to the event loop of your application to
  3465. recognize high-level events, and call the AEProcessAppleEvent function, as
  3466. described in the preceding two sections. You must also write handlers to handle
  3467. each Apple event; this section describes how to write these handlers.
  3468.  
  3469. _______________________________________________________________________________
  3470.  
  3471. æKY Required…Apple…Events
  3472. æC »Required Apple Events                                          The Apple Event Manager
  3473. _______________________________________________________________________________
  3474.  
  3475. When a user opens or prints a file from the Finder, the Finder sets up the
  3476. information your application can use to determine which files to open or print.
  3477. In version 7.0, if your application supports high-level events, the Finder
  3478. communicates this information to your application through the required Apple
  3479. events. 
  3480.  
  3481. The Finder sends one of the required Apple events to your application to request
  3482. that it open or print a list of documents, inform it that the Finder has just
  3483. opened your application, or inform it that the Finder is about to terminate your
  3484. application.
  3485.  
  3486. These are the required Apple events.
  3487.  
  3488.    Apple event                       Requested action
  3489.  
  3490.    Open Application             Perform tasks associated with opening your
  3491.    application 
  3492.  
  3493.    Open Documents              Open the specified documents 
  3494.  
  3495.    Print Documents               Print the specified documents
  3496.  
  3497.    Quit Application               Perform tasks—such as releasing memory,
  3498.    requesting 
  3499.                                                  the user to save documents, and
  3500.                                                  so on—associated with 
  3501.                                                  quitting; the Finder sends this
  3502.                                                  event to an application 
  3503.                                                  immediately after sending it a
  3504.                                                  Print Documents event or
  3505.                                                  if the user chooses Restart or
  3506.                                                  Shut Down from the 
  3507.                                                  Finder’s Special menu. 
  3508.  
  3509. The Finder uses the required Apple events as part of the new mechanisms in
  3510. system software version 7.0 for launching and terminating applications. This new
  3511. method of communicating Finder information to your application replaces the
  3512. mechanisms used in earlier versions of system software.
  3513.  
  3514. Applications that do not support high-level events can still use the
  3515. CountAppFiles, GetAppFiles, and ClrAppFiles procedures (or the GetAppParms
  3516. procedure) to get the Finder information. See the Segment Loader chapter of
  3517. Volume II for information on these routines. To make your application
  3518. 7.0-friendly and compatible with earlier versions of system software, it must
  3519. support both the old and new mechanisms.
  3520.  
  3521. Use the Gestalt function to determine whether the Apple Event Manager is
  3522. present. If it is and the isHighLevelEventAware flag is set in your
  3523. application’s 'SIZE' resource, your application receives the Finder information
  3524. through the required Apple events. 
  3525.  
  3526. If your application accepts high-level events, the Finder sends it an Open
  3527. Application, Open Documents, or Print Documents event immediately after
  3528. launching your application. Upon receiving any of these events, your application
  3529. should perform the action requested by the event.
  3530.  
  3531.    Note: This section describes the required Apple events as they are sent by
  3532.    the 
  3533.    Finder. When sent by other applications or processes, these same Apple 
  3534.    events—which are among the core Apple events described in the Apple Event 
  3535.    Registry—can include optional parameters not listed here. To be 7.0-friendly,
  3536.  
  3537.    your application only needs to handle the required parameters that are
  3538.    described 
  3539.    in this section.
  3540.  
  3541. Open Application—perform tasks associated with opening an application 
  3542.  
  3543. Event class                  kCoreEventClass
  3544.  
  3545. Event ID                      kAEOpenApplication
  3546.  
  3547. Parameters                  None
  3548.  
  3549. Requested action        Perform any tasks—such as opening an untitled document 
  3550.                                         window—that you would normally perform
  3551.                                         when a user 
  3552.                                         opens your application.
  3553.  
  3554. Open Documents—open the specified documents
  3555.  
  3556. Event class                    kCoreEventClass
  3557.  
  3558. Event ID                         kAEOpenDocuments
  3559.  
  3560. Required parameter    Keyword:                    keyDirectObject
  3561.                                          Descriptor type:         typeAEList
  3562.                                          Data:                            A list
  3563.                                          of alias records for the documents
  3564.                                                                               to
  3565.                                                                               be
  3566.  
  3567.  
  3568.  
  3569. Requested action          Open the documents specified in the keyDirectObject 
  3570.                                          parameter.
  3571.  
  3572. Print Documents—print the specified documents
  3573.  
  3574. Event class                     kCoreEventClass
  3575.  
  3576. Event ID                         kAEPrintDocuments
  3577.  
  3578. Required parameter    Keyword:                   keyDirectObject
  3579.                                          Descriptor type:        typeAEList
  3580.                                          Data:                           A list
  3581.                                          of alias records for the documents  
  3582.                                                                               to
  3583.  
  3584.  
  3585.  
  3586. Requested action         Print the documents specified in the keyDirectObject 
  3587.                                          parameter without opening windows for
  3588.                                          the documents. 
  3589.                                          The documents should remain open
  3590.                                          afterward.
  3591.  
  3592. Quit Application—perform tasks associated with quitting
  3593.  
  3594. Event class                      kCoreEventClass
  3595.  
  3596. Event ID                          kAEQuitApplication
  3597.  
  3598. Parameters                      None
  3599.  
  3600. Requested action           Perform any tasks that your application would
  3601. normally 
  3602.                                           perform when the user chooses Quit.
  3603.                                           Such tasks typically 
  3604.                                           include asking the user if he or she
  3605.                                           wants to save
  3606.                                           documents that have been changed. The
  3607.                                           Finder sends this 
  3608.                                           event to an application immediately
  3609.                                           after sending it a Print 
  3610.                                           Documents event or if the user chooses
  3611.                                           Restart or Shut 
  3612.                                           Down from the Finder’s Special menu.
  3613.  
  3614. Your application needs to recognize only two descriptor types to handle the
  3615. required Apple events:  descriptor lists and alias records. The Open Documents
  3616. event and Print Documents event use descriptor lists to store a list of
  3617. documents to open. Each document is specified as an alias record in the
  3618. descriptor list. 
  3619.  
  3620. You can retrieve the data that specifies the document to open as an alias
  3621. record, or you can request that the Apple Event Manager coerce the alias record
  3622. to a file system specification (FSSpec) record. The file system specification
  3623. record provides a standard method of identifying files in version 7.0. See the
  3624. File Manager chapter in this volume for a complete description of how to specify
  3625. files using file system specification records.
  3626. _______________________________________________________________________________
  3627.  
  3628. æKY Handling…the…Open…Application…Event
  3629. æC »Handling the Open Application Event                            The Apple Event Manager
  3630. _______________________________________________________________________________
  3631.  
  3632. To handle the Open Application event, your application should do just what it
  3633. does when the user opens your application. For example, your application might
  3634. open a new untitled document window in response to an Open Application event.
  3635.  
  3636. Listing 6-5 shows a handler that processes the Open Application event. The Open
  3637. Application event does not have any required parameters. This handler first
  3638. calls an application-defined function called MyGotRequiredParams. This function
  3639. checks whether the Apple event contains any required parameters. By definition,
  3640. the Open Application event should not contain any required parameters so, if the
  3641. Apple event does contain any, the handler returns an error. Otherwise the
  3642. handler opens a new document window.
  3643.  
  3644. ¿ Listing 6-5   A handler for the Open Application event
  3645.  
  3646. FUNCTION MyHandleOApp (theAppleEvent, reply: AppleEvent; 
  3647.                 handlerRefcon: LongInt) : OSErr;
  3648. VAR
  3649.    myErr: OSErr;
  3650. BEGIN
  3651.    myErr := MyGotRequiredParams (theAppleEvent);
  3652.    IF myErr <> noErr THEN
  3653.       MyHandleOApp := myErr
  3654.    ELSE
  3655.    BEGIN
  3656.       DoNew;
  3657.       MyHandleOApp := noErr;
  3658.    END;
  3659. END;
  3660.  
  3661. The MyGotRequiredParams function checks that all required parameters have been
  3662. extracted from the Apple event. See Listing 6-11 in “Writing Apple Event
  3663. Handlers” later in this chapter for a description of the MyGotRequiredParams
  3664. function.
  3665. _______________________________________________________________________________
  3666.  
  3667. æKY Handling…the…Open…Documents…Event
  3668. æC »Handling the Open Documents Event                              The Apple Event Manager
  3669. _______________________________________________________________________________
  3670.  
  3671. To handle the Open Documents event, your application should open the documents
  3672. specified in the Apple event. The Open Documents event contains a list of
  3673. documents to open in its direct parameter. Your application extracts this
  3674. information and then opens the specified documents.
  3675.  
  3676. Listing 6-6 shows a handler for the Open Documents event. The handler
  3677. illustrates how to open the documents referred to in the direct parameter.
  3678.  
  3679. ¿ Listing 6-6   A handler for the Open Documents event
  3680.  
  3681. FUNCTION MyHandleODoc (theAppleEvent, reply: AppleEvent;
  3682.                        handlerRefcon: LongInt) : OSErr;
  3683. VAR
  3684.    myFSS:               FSSpec;
  3685.    docList:             AEDescList;
  3686.    myErr:               OSErr;
  3687.    index, itemsInList:  LongInt;
  3688.    actualSize:          Size;
  3689.    keywd:               AEKeyword;
  3690.    returnedType:        DescType;
  3691. BEGIN
  3692.    {get the direct parameter--a descriptor list--and put it into docList}
  3693.    myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, 
  3694.                            docList);
  3695.    IF myErr <> noErr THEN DoError(myErr);
  3696.    {check for missing required parameters}
  3697.    myErr := MyGotRequiredParams(theAppleEvent);
  3698.    IF myErr <> noErr THEN     {an error occurred}
  3699.       BEGIN                   {do the necessary error handling}
  3700.          MyHandleODoc := myErr;
  3701.          Exit (MyHandleODoc);
  3702.       END;
  3703.    {count the number of descriptor records in the list}
  3704.    myErr := AECountItems (docList, itemsInList);
  3705.    {now get each descriptor record from the list, get the alias record }
  3706.    { out of it, and open the associated file}
  3707.    FOR index := 1 TO itemsInList DO
  3708.        BEGIN
  3709.           myErr := AEGetNthPtr(docList, index, typeFSS, keywd, 
  3710.                                returnedType, @myFSS, Sizeof(myFSS), 
  3711.                                actualSize);
  3712.           IF myErr <> noErr THEN DoError(myErr);
  3713.           myErr := MyOpenFile(@myFSS);
  3714.           IF myErr <> noErr THEN DoError(myErr);
  3715.        END;
  3716.    myErr := AEDisposeDesc(docList);
  3717.    MyHandleODoc := noErr;
  3718. END;
  3719.  
  3720. The handler in Listing 6-6 first uses the AEGetParamDesc function to get the
  3721. direct parameter (specified by the keyDirectObject keyword) out of the Apple
  3722. event. The handler requests that AEGetParamDesc return a descriptor list in the
  3723. docList variable. The handler then checks to make sure that it has retrieved all
  3724. of the required parameters by calling the MyGotRequiredParams function (see
  3725. Listing 6-11 for a description of this routine).
  3726.  
  3727. Once the handler has retrieved the descriptor list from the Apple event, it uses
  3728. AECountItems to count the number of descriptors in the list. Using the returned
  3729. number as an index, the handler can get the data of each descriptor record in
  3730. the list. This handler requests that the AEGetNthPtr function coerce the data in
  3731. the descriptor record to a file system specification record. The handler can
  3732. then use the file system specification record as a parameter to its own routine
  3733. for opening files.
  3734.  
  3735. For more information on the AEGetParamDesc function, see “Getting Data out of
  3736. Parameters” later in this chapter. Also see “Getting Data out of Descriptor
  3737. Lists” for further information on the AEGetNthPtr and AECountItems functions.
  3738.  
  3739. After extracting the file system specification record that describes the
  3740. document to open, your application can use this record to open the file. For
  3741. example, in Listing 6-6, the code passes the file system specification record to
  3742. its routine for opening files, the MyOpenFile function. 
  3743.  
  3744. The MyOpenFile function is designed so that it can be called both in response to
  3745. the Open Documents event and to events generated by the user. For example, when
  3746. the user chooses Open from the File menu, the code that handles the mouse-down
  3747. event uses the StandardGetFile procedure to let the user choose a file; it then
  3748. calls MyOpenFile, passing the file system specification record returned by
  3749. StandardGetFile. By isolating code that performs a requested action from code
  3750. that interacts with the user, you can easily adapt your application to handle
  3751. Apple events that request the same action. 
  3752.  
  3753. Note that your handler should use the AEDisposeDesc function to dispose of the
  3754. descriptor list when your handler no longer requires the data in it. Your
  3755. handler should also return a result code.
  3756. _______________________________________________________________________________
  3757.  
  3758. æKY Handling…the…Print…Documents…Event
  3759. æC »Handling the Print Documents Event                             The Apple Event Manager
  3760. _______________________________________________________________________________
  3761.  
  3762. To handle the Print Documents event, your application should print the documents
  3763. specified in the Apple event. The Print Documents event contains a list of
  3764. documents to print in its direct parameter. Your application extracts this
  3765. information and then prints the specified documents. Your application should not
  3766. open any windows for the documents. Also note that your application should
  3767. remain open after processing the Print Documents event; the Finder sends your
  3768. application a Quit Application event immediately after sending it a Print
  3769. Documents event.
  3770.  
  3771. Listing 6-7 shows a handler for the Print Documents event. This handler is
  3772. similar to the handler for the Open Documents event. The code illustrates how to
  3773. print the documents referred to in the direct parameter.
  3774.  
  3775. ¿ Listing 6-7   A handler for the Print Documents event
  3776.  
  3777. FUNCTION MyHandlePDoc (theAppleEvent, reply: AppleEvent;
  3778.                        handlerRefcon: LongInt) : OSErr;
  3779. VAR
  3780.    myFSS:               FSSpec;
  3781.    docList:             AEDescList;
  3782.    myErr:               OSErr;
  3783.    index, itemsInList:  LongInt;
  3784.    actualSize:          Size;
  3785.    keywd:               AEKeyword;
  3786.    returnedType:        DescType;
  3787. BEGIN
  3788.    {get the direct parameter--a descriptor list--and put it into docList}
  3789.    myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, 
  3790.                            docList);
  3791.    IF myErr <> noErr THEN DoError(myErr);
  3792.       {check for missing required parameters}
  3793.       myErr := MyGotRequiredParams(theAppleEvent);
  3794.    IF myErr <> noErr THEN {an error occurred}
  3795.       BEGIN
  3796.          {do the necessary error handling}
  3797.          MyHandlePDoc := myErr;
  3798.          Exit(MyHandlePDoc);
  3799.       END;
  3800.    {count the number of descriptor records in the list}
  3801.    myErr := AECountItems (docList, itemsInList);
  3802.    {now get each descriptor record from the list, get the alias record }
  3803.    { out of  it, and print the associated file}
  3804.    FOR index := 1 TO itemsInList DO
  3805.        BEGIN
  3806.        myErr := AEGetNthPtr(docList, index, typeFSS, keywd, returnedType,
  3807.                             @myFSS, Sizeof(myFSS), actualSize);
  3808.        IF myErr <> noErr THEN DoError(myErr);
  3809.        MyPrintFile(@myFSS);
  3810.        END;
  3811.    myErr := AEDisposeDesc(docList);
  3812.    MyHandlePDoc := noErr;
  3813. END;
  3814. _______________________________________________________________________________
  3815.  
  3816. æKY Handling…the…Quit…Application…Event
  3817. æC »Handling the Quit Application Event                            The Apple Event Manager
  3818. _______________________________________________________________________________
  3819.  
  3820. To handle the Quit Application event, your application should take any actions
  3821. that are necessary before it is terminated (such as saving any open documents).
  3822. Listing 6-8 shows an example of a handler for the Quit Application event.
  3823.  
  3824. The Finder sends your application a Quit Application event immediately after a
  3825. Print Documents event. The Finder also sends your application a Quit Application
  3826. event if the user chooses Restart or Shut Down from the Finder’s Special menu. 
  3827.  
  3828. ¿ Listing 6-8   A handler for the Quit Application event
  3829.  
  3830. FUNCTION MyHandleQuit (theAppleEvent, reply: AppleEvent;
  3831.                        handlerRefcon: LongInt) : OSErr;
  3832. VAR
  3833.    userCanceled : Boolean;
  3834. BEGIN
  3835.    {check for missing required parameters}
  3836.    myErr := MyGotRequiredParams (theAppleEvent);
  3837.    IF myErr <> noErr THEN {an error occurred}
  3838.       BEGIN
  3839.          {do the necessary error handling}
  3840.          MyHandleQuit := myErr;
  3841.          Exit (MyHandleQuit);
  3842.       END;
  3843.    userCanceled := MyPrepareToTerminate;
  3844.    IF userCanceled THEN
  3845.       MyHandleQuit := userCanceledErr
  3846.    ELSE
  3847.       MyHandleQuit := noErr;
  3848. END;
  3849.  
  3850. The handler in Listing 6-8 calls another function supplied by the application,
  3851. the MyPrepareToTerminate function. This function saves the documents for any
  3852. open windows and returns a Boolean value that indicates whether the Quit request
  3853. was canceled by the user. This is another example of isolating code for
  3854. interacting with the user from the code that performs the requested action.
  3855. Structuring your application in this way allows your application to use the same
  3856. routine when responding to a user event (such as choosing the Quit command from
  3857. the File menu) or to the corresponding Apple event. (For a description of the
  3858. MyGotRequiredParams function, see “Writing Apple Event Handlers” later in this
  3859. chapter.)
  3860.  
  3861. Note that your handler must not call the ExitToShell procedure. In Listing 6-8,
  3862. the application calls the ExitToShell procedure only if the handler returns
  3863. noErr as its function result.
  3864. _______________________________________________________________________________
  3865.  
  3866. æKY Handling…Apple…Events…Sent…by…the…Edition…Manager
  3867. æC »Handling Apple Events Sent by the Edition Manager              The Apple Event Manager
  3868. _______________________________________________________________________________
  3869.  
  3870. If your application provides publish and subscribe capabilities, it should
  3871. handle the Apple events sent by the Edition Manager in addition to the required
  3872. Apple events. Your application should also handle the Create Publisher event.
  3873. The Create Publisher event is described in the next section.
  3874.  
  3875. The Edition Manager sends your application Apple events to communicate
  3876. information about the publishers and subscribers in your application’s
  3877. documents. Specifically, the Edition Manager uses Apple events to notify your
  3878. application 
  3879.  
  3880.   • when the information in an edition is updated
  3881.  
  3882.   • when your application needs to write the data from a publisher to an edition
  3883.  
  3884.   • when your application should locate a particular publisher and scroll the 
  3885.      document to that location
  3886.  
  3887. The Apple events sent by the Edition Manager to your application are the Section
  3888. Read event, Section Write event, and Section Scroll event.
  3889.  
  3890. Section Read—read information into the specified section
  3891.  
  3892. Event class                     SectionEventMsgClass
  3893.  
  3894. Event ID                         SectionReadMsgID
  3895.  
  3896. Required parameter    Keyword:                keyDirectObject
  3897.                                          descriptor type:      typeSectionH
  3898.                                          Data:                         A handle
  3899.                                          to the section record of the 
  3900.  
  3901.                                                                            whose
  3902.  
  3903.  
  3904.  
  3905.  
  3906.  
  3907.  
  3908.  
  3909. Requested action          Update the subscriber with the new information from
  3910. the 
  3911.                                          edition.
  3912.  
  3913. Section Write—write the specified section to an edition
  3914.  
  3915. Event class                       SectionEventMsgClass
  3916.  
  3917. Event ID                           SectionWriteMsgID
  3918.  
  3919. Required parameter      Keyword:                keyDirectObject
  3920.                                            descriptor type:      typeSectionH
  3921.                                            Data:                         A
  3922.                                            handle to the section record of the 
  3923.  
  3924.  
  3925.  
  3926. Requested action           Write the publisher’s data to its edition.
  3927.  
  3928. Section Scroll—scroll the document to the specified section
  3929.  
  3930. Event class                       SectionEventMsgClass
  3931.  
  3932. Event ID                           SectionScrollMsgIDi.SectionScrollMsgID event
  3933. ID  6-;
  3934.  
  3935. Required parameter      Keyword:                 keyDirectObject
  3936.                                            descriptor type:       typeSectionH
  3937.                                            Data:                          A
  3938.                                            handle to the section record of the 
  3939.  
  3940.                                                                               to
  3941.  
  3942.  
  3943.  
  3944.  
  3945. Requested action           Scroll the document to the publisher identified by
  3946. the 
  3947.                                            specified section record. 
  3948.  
  3949. See the Edition Manager chapter in this volume for details on how your
  3950. application should respond to these events.
  3951. _______________________________________________________________________________
  3952.  
  3953. æKY Handling…the…Create…Publisher…Event
  3954. æC »Handling the Create Publisher Event                            The Apple Event Manager
  3955. _______________________________________________________________________________
  3956.  
  3957. If your application supports publish and subscribe capabilities, it should also
  3958. handle the Create Publisher event.
  3959.  
  3960. Create Publisher—create a publisher
  3961.  
  3962. Event class                       kAEMiscStdSuite
  3963.  
  3964. Event ID                           kAECreatePublisher
  3965.  
  3966. Required parameter       none
  3967.  
  3968. Optional parameter        Keyword:                keyDirectObject
  3969.                                              descriptor type:
  3970.                                              typeObjectSpecifier
  3971.                                              Data:                       The
  3972.                                              part of the document to publish. If
  3973.  
  3974.  
  3975.  
  3976.                                                                               is
  3977.  
  3978.  
  3979.  
  3980.  
  3981.  
  3982.  
  3983.  
  3984.  
  3985. Optional parameter        Keyword:                keyAEEditionFileLoc
  3986.                                             descriptor type:      typeAlias
  3987.                                             Data:                         An
  3988.                                             alias record that contains the 
  3989.  
  3990.  
  3991.  
  3992.  
  3993.  
  3994.  
  3995.  
  3996.  
  3997.  
  3998.  
  3999.  
  4000.  
  4001.  
  4002.  
  4003.  
  4004.  
  4005.  
  4006.  
  4007.  
  4008.  
  4009.  
  4010. Requested action             Create a publisher for the specified data using the
  4011. specified 
  4012.                                              location for the edition container.
  4013.                                              If the data isn’t specified,
  4014.                                              publish the current selection. If
  4015.                                              the location of the edition 
  4016.                                               isn’t specified, use the default
  4017.                                               location.
  4018.  
  4019. When your application receives the Create Publisher event, it should create a
  4020. publisher by writing the publisher's data to an edition. The data of the
  4021. publisher, and the location and name of the edition, are defined by the Apple
  4022. event. If the Create Publisher event includes a keyDirectObject parameter, then
  4023. your application should publish the data contained in the parameter. If the
  4024. keyDirectObject parameter is missing, then your application should publish the
  4025. current selection. If the document doesn’t have a current selection, your
  4026. handler for the event should return a non-zero result code.
  4027.  
  4028. If the Create Publisher event includes a keyAEEditionFileLoc parameter, then
  4029. your application should use the location and name contained in the parameter as
  4030. the default location and name of the edition. If the keyAEEditionFileLoc
  4031. parameter is missing, then your application should use the default location and
  4032. name your application normally uses to specify the edition container.
  4033.  
  4034. Listing 6-9 shows a handler for the Create Publisher event. This handler checks
  4035. for the keyDirectObject parameter and the keyAEEditionFileLoc parameter. If
  4036. either of these are not specified, the handler uses default values. The handler
  4037. uses the DoNewPublisher function, an application-defined function, to create the
  4038. publisher and its edition, create a section record, and update other data
  4039. structures associated with the document. See Listing 4-4 in the Edition Manager
  4040. chapter for an example of the DoNewPublisher function.
  4041.  
  4042. Note that the handler uses the AEInteractWithUser function to determine if user
  4043. interaction is allowed. If user interaction is allowed, the handler sets the
  4044. promptForDialog variable to TRUE, indicating that the DoNewPublisher function
  4045. should display the publisher dialog box. If user interaction is not allowed, the
  4046. handler sets the promptForDialog variable to FALSE, and the DoNewPublisher
  4047. function does not prompt the user for the location or name of the edition.
  4048.  
  4049. ¿ Listing 6-9   Handler for the Create Publisher event
  4050.  
  4051. FUNCTION MyHandleCreatePublisherEvent(theAppleEvent, reply: AppleEvent; 
  4052.                                       handlerRefcon: LongInt) : OSErr;
  4053. VAR
  4054. myErr:                  OSErr;
  4055. returnedType:           DescType;
  4056. thePublisherDataDesc:   AEDesc;
  4057. actualSize:             LongInt;
  4058. promptForDialog:        Boolean;
  4059. thisDocument:           MyDocumentInfoPtr;
  4060. preview:                Handle; 
  4061. previewFormat:          FormatType; 
  4062. defaultLocation:        EditionContainerSpec;
  4063.  
  4064. BEGIN
  4065.    MyGetDocumentPtr(thisDocument);
  4066.    myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, 
  4067.                            typeObjectSpecifier, thePublisherDataDesc);
  4068.    CASE myErr OF
  4069.         errAEDescNotFound: 
  4070.         BEGIN
  4071.            {use the current selection as the publisher }
  4072.            { set up info for later when DoNewPublisher displays preview}
  4073.            preview := MyGetPreviewForSelection(thisDocument);
  4074.            previewFormat := 'TEXT';
  4075.         END
  4076.         noErr: 
  4077.            {Use the data in keyDirectObject parameter as the publisher }
  4078.            { (which is returned in thePublisherDataDesc variable) }
  4079.            { set up info for later when DoNewPublisher displays preview}
  4080.            MySetInfoForPreview(thePublisherDataDesc, thisDocument, 
  4081.                                preview, previewFormat);
  4082.         OTHERWISE
  4083.             DoError(myErr);
  4084.    END;
  4085.    myErr := AEGetParamPtr(theAppleEvent, keyAEEditionFileLoc, 
  4086.                           typeFSS, returnedType, 
  4087.                           @defaultLocation.theFile,
  4088.                           SizeOf(FSSpec), actualSize);
  4089.    CASE myErr OF
  4090.       errAEDescNotFound: 
  4091.          {use the default location as the edition container}
  4092.               myErr := MyGetDefaultEditionSpec(thisDocument, 
  4093.                                                defaultLocation);
  4094.       noErr: 
  4095.       BEGIN       {The keyAEEditionFileLoc parameter }
  4096.                   { contained a default location}
  4097.          defaultLocation.thePart := kPartsNotUsed;
  4098.          defaultLocation.theFileScript := smSystemScript;
  4099.       END
  4100.       OTHERWISE
  4101.          DoError(myErr);
  4102.       END;
  4103.    myErr := MyGotRequiredParams(theAppleEvent);
  4104.    IF myErr <> noErr THEN
  4105.       BEGIN
  4106.       {handle the error appropriately}
  4107.       MyHandleCreatePublisherEvent := myErr;
  4108.       END;
  4109.    promptForDialog := (AEInteractWithUser(kAEDefaultTimeout, NIL,
  4110.                                           @MyIdleFunction) = noErr);  
  4111.    myErr := DoNewPublisher(thisDocument, promptForDialog, 
  4112.                            preview, previewFormat, defaultLocation);
  4113.    {add keyErrorNumber and keyErrorString parameters if desired}
  4114.    MyHandleCreatePublisherEvent := myErr;
  4115. END;
  4116. _______________________________________________________________________________
  4117.  
  4118. æKY Getting…Data…out…of…an…Apple…Event
  4119. æC »Getting Data out of an Apple Event                             The Apple Event Manager
  4120. _______________________________________________________________________________
  4121.  
  4122. The Apple Event Manager stores the parameters and attributes of an Apple event
  4123. in a format that is internal to the Apple Event Manager. You use Apple Event
  4124. Manager functions to retrieve the data from an Apple event and return it to your
  4125. application in a format your application can use.
  4126.  
  4127. The Apple Event Manager provides functions that retrieve data from parameters
  4128. and attributes. Most of these functions are available in two forms: one that
  4129. returns the desired data in a specified buffer and one that returns a descriptor
  4130. record containing the same data. For example, the AEGetParamPtr function returns
  4131. the data of a specified parameter, and the AEGetParamDesc function returns the
  4132. descriptor record of a specified parameter. 
  4133.  
  4134. You can also use Apple Event Manager functions to get data out of descriptor
  4135. records, descriptor lists, and AE records. You use similar functions to put data
  4136. into descriptor records, descriptor lists, and AE records.
  4137.  
  4138. When your handler receives an Apple event, you’ll typically use the
  4139. AEGetParamPtr, AEGetAttrPtr, AEGetParamDesc, or AEGetAttrDesc function to get
  4140. the data out of the Apple event.
  4141.  
  4142. Some Apple Event Manager functions let your application request that the data be
  4143. returned using any descriptor type, even if it is different from the original
  4144. descriptor type. If the original data is of a different descriptor type, the
  4145. Apple Event Manager attempts to coerce the data to the requested descriptor
  4146. type.
  4147.  
  4148. For example, the AEGetParamPtr function lets you specify the desired descriptor
  4149. type of the resulting data.
  4150.  
  4151. VAR
  4152. theAppleEvent:   AppleEvent;
  4153. returnedType:    DescType;
  4154. multResult:      LongInt;
  4155. actualSize:      Size;
  4156. myErr:           OSErr;
  4157.  
  4158. myErr := AEGetParamPtr(theAppleEvent, keyMultResult, typeLongInteger, 
  4159.                        returnedType, @multResult, SizeOf(multResult), 
  4160.                        actualSize);
  4161.  
  4162. In this example, the desired type is specified in the third parameter by the
  4163. typeLongInteger descriptor type. This requests that the Apple Event Manager
  4164. coerce the data to the type defined by this descriptor type (a long integer) if
  4165. it is not already of this type. 
  4166.  
  4167. To ensure that no coercion is performed and that the descriptor type of the
  4168. result is of the same type as the original, you can specify typeWildCard for the
  4169. desired descriptor type.
  4170.  
  4171. The Apple Event Manager returns the descriptor type of the resulting data in the
  4172. fourth parameter. This is useful information when you specify typeWildCard as
  4173. the desired descriptor type; you can determine the descriptor type of the
  4174. resulting data by examining the fourth parameter.
  4175.  
  4176. The Apple Event Manager can coerce many different types of data into another.
  4177. For example, the Apple Event Manager can convert alias records to file system
  4178. specification records, integers to Boolean data types, and characters to numeric
  4179. data types, in addition to other data type conversions.
  4180.  
  4181. You can also provide your own coercion handlers to coerce other data types. See
  4182. “Writing and Installing Coercion Handlers” later in this chapter for information
  4183. on the coercion provided by the Apple Event Manager and how to provide your own
  4184. coercion handlers.
  4185.  
  4186. Parameters are keyword-specified descriptor records. You can use AEGetParamDesc
  4187. to get the descriptor record of a parameter, or you can use AEGetParamPtr to get
  4188. the data out of the descriptor record of a parameter. Attributes are also
  4189. keyword-specified descriptor records, and you can use similar routines to get
  4190. the descriptor record of an attribute or to get the data out of an attribute.
  4191.  
  4192. The following sections show examples of how to use the AEGetParamPtr,
  4193. AEGetAttrPtr, AEGetParamDesc, or AEGetAttrDesc function to get the data out of
  4194. an Apple event.
  4195. _______________________________________________________________________________
  4196.  
  4197. æKY Getting…Data…out…of…a…Parameter
  4198. æC »Getting Data out of a Parameter                                The Apple Event Manager
  4199. _______________________________________________________________________________
  4200.  
  4201. You can use the AEGetParamPtr or AEGetParamDesc function to get the data out of
  4202. a parameter. Use the AEGetParamPtr function to return the data contained in a
  4203. parameter. Use the AEGetParamDesc function when you need to get the descriptor
  4204. record of a parameter. You often use the AEGetParamDesc function to extract the
  4205. descriptor list from a parameter.
  4206.  
  4207. You can also use the AEGetKeyPtr function to return the data contained in a
  4208. parameter. The AEGetKeyPtr function provides an additional feature; you can use
  4209. this function to get data out of an AE record. See “Getting Data and
  4210. Keyword-Specified Descriptor Records From AE Records” later in this chapter for
  4211. information on this function.
  4212.  
  4213. For example, you use an Apple Event Manager function to get the data out of a
  4214. Section Read event. The Edition Manager sends your application a Section Read
  4215. event to tell your application to read updated information from an edition into
  4216. the specified subscriber. The direct parameter of the Apple event contains a
  4217. handle to the section record of the subscriber. You can use the AEGetParamPtr
  4218. function to get the data out of the Apple event.
  4219.  
  4220. You specify the Apple event that contains the desired parameter, the keyword of
  4221. the desired parameter, the descriptor type the function should use to return the
  4222. data, a buffer to store the data, and the size of this buffer as parameters to
  4223. the AEGetParamPtr function. The AEGetParamPtr function returns the descriptor
  4224. type of the resulting data and the actual size of the data, and it places the
  4225. requested data in the specified buffer.
  4226.  
  4227. VAR
  4228. SectionH:          sectionHandle;
  4229. theAppleEvent:     AppleEvent;
  4230. returnedType:      DescType;
  4231. actualSize:        Size;
  4232. myErr:             OSErr;
  4233.  
  4234. myErr := AEGetParamPtr(theAppleEvent, keyDirectObject, typeSectionH, 
  4235.                        returnedType, @sectionH, SizeOf(sectionH), 
  4236.                        actualSize);
  4237.  
  4238. In this example, the keyDirectObject keyword specifies that the AEGetParamPtr
  4239. function should extract information from the direct parameter; AEGetParamPtr
  4240. returns the data in the buffer specified by the sectionH variable. 
  4241.  
  4242. You can request that the Apple Event Manager return the data using the
  4243. descriptor type of the original data or you can request that the Apple Event
  4244. Manager coerce the data into a descriptor type that is different from the
  4245. original. You can specify the desired descriptor type as typeWildCard if you
  4246. don’t want any coercion performed—in which case, the AEGetParamPtr function
  4247. returns the original descriptor type of the parameter.
  4248.  
  4249. The typeSectionH descriptor type specifies that the returned data should be
  4250. coerced to a handle to a section record. In this example, the Apple Event
  4251. Manager automatically coerces the data from a temporary ID to a handle to a
  4252. section record when you specify the typeSectionH descriptor type. You can use
  4253. the information returned in the sectionH variable to identify the subscriber and
  4254. read in the information from the edition.
  4255.  
  4256. In this example, the AEGetParamPtr function returns in the returnedType variable
  4257. the descriptor type of the resulting data. In most cases, the descriptor type of
  4258. the resulting data matches the requested descriptor type, unless the Apple Event
  4259. Manager wasn’t able to coerce the data to the specified descriptor type. If the
  4260. coercion fails, the Apple Event Manager returns the errAECoercionFail result
  4261. code.
  4262.  
  4263. The AEGetParamPtr function returns the actual size of the data in the actualSize
  4264. variable. If the value returned in the actualSize variable is greater than the
  4265. amount your application allocated for the buffer to hold the returned data, your
  4266. application can increase the size of its buffer to this amount, and get the data
  4267. again. You can also choose to use the AEGetParamDesc function when your
  4268. application doesn’t know the size of the data.
  4269.  
  4270. You can use the AEGetParamDesc function to return the descriptor record of a
  4271. parameter. This function is useful, for example, when extracting descriptor
  4272. lists from a parameter.
  4273.  
  4274. You specify the Apple event that contains the desired parameter, the keyword of
  4275. the desired parameter, the descriptor type the function should use to return the
  4276. descriptor record, and a buffer to store the returned descriptor record as
  4277. parameters to the AEGetParamDesc function. The AEGetParamDesc function returns
  4278. the descriptor record using the specified descriptor type. 
  4279.  
  4280. For example, the direct parameter of the Open Documents event contains a
  4281. descriptor list that specifies the documents to open. You can use the
  4282. AEGetParamDesc function to get the descriptor list out of the direct parameter.
  4283.  
  4284. VAR
  4285. docList:           AEDescList;
  4286. theAppleEvent:     AppleEvent;
  4287. myErr:             OSErr;
  4288.  
  4289. myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, 
  4290.                         docList);
  4291.  
  4292. In this example, the Apple event specified by the variable theAppleEvent
  4293. contains the desired parameter. The keyDirectObject keyword specifies that the
  4294. AEGetParamDesc function should get the descriptor record of the direct
  4295. parameter. The typeAEList descriptor type specifies that the descriptor record
  4296. should be returned as a descriptor list. In this example, the AEGetParamDesc
  4297. function returns a descriptor list in the docList variable.
  4298.  
  4299. The descriptor list contains a list of descriptor records. To get the descriptor
  4300. records and their data out of a descriptor list, use the AECountItems function
  4301. to find the number of descriptor records in the list, and then make repetitive
  4302. calls to the AEGetNthPtr function to get the data out of each descriptor record.
  4303. See “Getting Data out of a Descriptor List” later in this chapter for more
  4304. information.
  4305.  
  4306. Note that the AEGetParamDesc function copies the descriptor record from the
  4307. parameter. When you’re done with a descriptor record that you obtained from
  4308. AEGetParamDesc, you must dispose of it by calling the AEDisposeDesc function.
  4309. _______________________________________________________________________________
  4310.  
  4311. æKY Getting…Data…out…of…an…Attribute
  4312. æC »Getting Data out of an Attribute                               The Apple Event Manager
  4313. _______________________________________________________________________________
  4314.  
  4315. You can use the AEGetAttributePtr or AEGetAttributeDesc function to get the data
  4316. out of the attributes of an Apple event.
  4317.  
  4318. You can get the data out of an attribute using the AEGetAttributePtr function.
  4319. You specify the Apple event that contains the desired attribute, the keyword of
  4320. the desired attribute, the descriptor type the function should use to return the
  4321. data, a buffer to store the data, and the size of this buffer as parameters to
  4322. the AEGetAttributePtr function. The AEGetAttributePtr function returns the
  4323. descriptor type of the returned data and the actual size of the data, and it
  4324. places the requested data in the specified buffer.
  4325.  
  4326. For example, this code gets the data out of the keyEventSourceAttr attribute of
  4327. an Apple event.
  4328.  
  4329. VAR
  4330. theAppleEvent:   AppleEvent;
  4331. returnedType:    DescType;
  4332. sourceOfAE:      Integer;
  4333. actualSize:      Size;
  4334. myErr:           OSErr;
  4335.  
  4336. myErr := AEGetAttributePtr(theAppleEvent, keyEventSourceAttr, 
  4337.                            typeShortInteger, returnedType, sourceOfAE,
  4338.                            SizeOf(sourceOfAE), actualSize);
  4339.  
  4340. The keyEventSourceAttr keyword specifies the attribute to get the data from. The
  4341. typeShortInteger descriptor type specifies that the data should be returned as a
  4342. short integer; the returnedType variable contains the actual descriptor type
  4343. that is returned. You also must specify a buffer to hold the returned data, and
  4344. specify the size of this buffer. The AEGetAttributePtr function returns the
  4345. actual size of the data returned in the actualSize variable. You can check this
  4346. value to make sure you got all the data.
  4347.  
  4348. As with the AEGetParamPtr function, you can request that AEGetAttributePtr
  4349. return the data using the descriptor type of the original data, or you can
  4350. request that the Apple Event Manager coerce the data into a descriptor type that
  4351. is different from the original. 
  4352.  
  4353. In this example, the AEGetAttributePtr function returns the requested data in
  4354. the sourceOfAE variable, and you can determine the source of the Apple event by
  4355. examining this value.
  4356.  
  4357. The next example shows how to use the AEGetAttributePtr function to get data out
  4358. of the keyMissedKeywordAttr attribute. After your handler extracts all known
  4359. parameters from an Apple event, it should check whether the keyMissedKeywordAttr
  4360. attribute exists. If it does, then your handler did not get all of the required
  4361. parameters.
  4362.  
  4363. Note that if AEGetAttributePtr returns the errAEDescNotFound result code, then
  4364. the keyMissedKeywordAttr does not exist—which indicates that your application
  4365. has extracted all of the required parameters. If AEGetAttributePtr returns
  4366. noErr, then the keyMissedKeywordAttr does exist—which indicates that your
  4367. handler did not get all of the required parameters.
  4368.  
  4369. myErr := AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, 
  4370.                            typeWildCard, returnedType, NIL, 0, 
  4371.                            actualSize);
  4372.  
  4373. The data in the keyMissedKeywordAttr attribute contains the first required
  4374. parameter, if any, that your handler didn’t retrieve. If you want this data
  4375. returned, specify a buffer to hold the data and specify the size of the buffer.
  4376. Otherwise, as in this example, specify NIL as the buffer and 0 as the size of
  4377. the buffer.
  4378. _______________________________________________________________________________
  4379.  
  4380. æKY Getting…Data…out…of…a…Descriptor…List
  4381. æC »Getting Data out of a Descriptor List                          The Apple Event Manager
  4382. _______________________________________________________________________________
  4383.  
  4384. You can use the AECountItems function to count the number of items in a
  4385. descriptor list, and you can use AEGetNthDesc or AEGetNthPtr to get a descriptor
  4386. record or its data out of a descriptor list.
  4387.  
  4388. The Open Documents event contains a direct parameter that specifies the list of
  4389. documents to open. The list of documents is contained in a descriptor list.
  4390. After extracting the descriptor list from the parameter, you can determine the
  4391. number of items in the list and then extract each descriptor record from the
  4392. descriptor list. See Figure 6-6 in “Data Structures Within Apple Events” earlier
  4393. in this chapter for a depiction of the Open Documents event.
  4394.  
  4395. For example, when your handler receives an Open Documents event, you can use the
  4396. AEGetParamDesc function to return the direct parameter as a descriptor list. You
  4397. can then use AECountItems to return the number of descriptor records in the
  4398. list.
  4399.  
  4400. VAR
  4401. theAppleEvent:    AppleEvent;
  4402. docList:          AEDescList;
  4403. itemsInList:      LongInt;
  4404. myErr:            OSErr;
  4405.  
  4406. myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, 
  4407.                         docList);
  4408. myErr := AECountItems(docList, itemsInList);
  4409.  
  4410. The AEGetParamDesc function returns in the docList variable the descriptor list
  4411. from the direct parameter of the Open Documents event. You specify this list to
  4412. the AECountItems function.
  4413.  
  4414. You specify the descriptor list whose items you want to count in the first
  4415. parameter to AECountItems. The Apple Event Manager returns the number of items
  4416. in the list in the second parameter. When extracting the descriptor records from
  4417. a list, you often use the number of items as a loop index. Here’s an example:
  4418.  
  4419. FOR index := 1 TO itemsInList DO
  4420.    BEGIN
  4421.    {for each descriptor record in the list, get its data}
  4422.    END;
  4423.  
  4424. The format of the descriptor records in a descriptor list is private to the
  4425. Apple Event Manager. You must use the AEGetNthPtr or AEGetNthDesc function to
  4426. extract descriptor records from a descriptor list.
  4427.  
  4428. You specify the descriptor list that contains the desired descriptor records and
  4429. an index as parameters to the AEGetNthPtr function. The index represents a
  4430. specific descriptor record in the descriptor list. The AEGetNthPtr returns the
  4431. data from the descriptor record represented by the specified index. 
  4432.  
  4433. You also specify the descriptor type the function should use to return the data,
  4434. a buffer to store the data, and the size of this buffer. The AEGetNthPtr
  4435. function returns the keyword of the parameter, the descriptor type of the
  4436. returned data, and the actual size of the data, and it places the requested data
  4437. in the specified buffer.
  4438.  
  4439. Here’s an example that uses the AEGetNthPtr function to extract an item from the
  4440. descriptor list in the direct parameter of the Open Documents event. 
  4441.  
  4442. myErr := AEGetNthPtr(docList, index, typeFSS, keywd, returnedType,
  4443.                      @myFSS, Sizeof(myFSS), actualSize);
  4444.  
  4445. The docList variable specifies the descriptor list from the direct parameter of
  4446. the Open Documents event. The index variable specifies the index of the
  4447. descriptor record to extract. You can use the typeFSS descriptor type, as in
  4448. this example, to specify that the data be returned as a file system
  4449. specification record. The Apple Event Manager automatically coerces the original
  4450. data type of the descriptor record from an alias record to a file system
  4451. specification record. The AEGetNthPtr function returns the keyword of the
  4452. parameter in the keywd variable. The function returns in the returnedType
  4453. variable the descriptor type of the resulting data. 
  4454.  
  4455. You specify a buffer to hold the desired data and the size (in bytes) of the
  4456. buffer as parameters to the AEGetNthPtr function. In this example, the myFSS
  4457. variable specifies the buffer. The function returns the actual size of the data
  4458. in the actualSize variable. If this size is larger than the size of the buffer
  4459. you provided, you know that you didn’t get all of the data for the descriptor
  4460. record.
  4461.  
  4462. Listing 6-10 shows a more complete example of extracting the items from a
  4463. descriptor list in the Open Documents event.
  4464.  
  4465. ¿ Listing 6-10   Extracting items from a descriptor list
  4466.  
  4467. VAR
  4468. index:          LongInt;
  4469. itemsInList:    LongInt;
  4470. docList:        AEDescList;
  4471. keywd:          AEKeyword;
  4472. returnedType:   DescType;
  4473. myFSS:          FSSpec;
  4474. actualSize:     Size;
  4475. myErr:         OSErr;
  4476.  
  4477. FOR index := 1 TO itemsInList DO
  4478.     BEGIN
  4479.         myErr := AEGetNthPtr(docList, index, typeFSS, keywd, returnedType ,
  4480.                              @myFSS, Sizeof(myFSS), actualSize);
  4481.         IF myErr <> noErr THEN DoError(myErr);
  4482.         myErr := MyOpenFile(@myFSS);
  4483.         IF myErr <> noErr THEN DoError(myErr);
  4484.     END;
  4485.     myErr := AEDisposeDesc(docList); 
  4486. _______________________________________________________________________________
  4487.  
  4488. æKY Writing…Apple…Event…Handlers
  4489. æC »Writing Apple Event Handlers                                   The Apple Event Manager
  4490. _______________________________________________________________________________
  4491.  
  4492. For each Apple event your application supports, you must provide a function
  4493. called an Apple event handler. The AEProcessAppleEvent function calls one of
  4494. your Apple event handlers when it processes an Apple event. Your Apple event
  4495. handlers should perform any action requested by the Apple event, add parameters
  4496. to the reply Apple event if appropriate, and return a result code.
  4497.  
  4498. The Apple Event Manager uses dispatch tables to route Apple events to the
  4499. appropriate Apple event handler. You must supply an Apple event handler for each
  4500. entry in your application’s Apple event dispatch table. Each handler must be a
  4501. function that uses this syntax:
  4502.  
  4503. FUNCTION MyEventHandler (theAppleEvent: AppleEvent; reply: AppleEvent;
  4504.                          handlerRefcon: LongInt) : OSErr; 
  4505.  
  4506. The parameter theAppleEvent is the Apple event to handle. Your handler uses
  4507. Apple Event Manager functions to extract any parameters and attributes from the
  4508. Apple event and then performs the necessary processing. The reply parameter is
  4509. the default reply provided by the Apple Event Manager. (“Replying to an Apple
  4510. Event,” later in this chapter, describes how to add parameters to the default
  4511. reply.) The handlerRefcon parameter is the reference constant stored in the
  4512. Apple event dispatch table entry for the Apple event. Your handler can ignore
  4513. this parameter if your application does not use the reference constant.
  4514.  
  4515. After extracting all known parameters from the Apple event, every handler should
  4516. determine whether the Apple event contains any further required parameters. Your
  4517. handler can check that it retrieved all the required parameters by checking
  4518. whether the keyMissedKeywordAttr attribute exists. If the attribute exists, then
  4519. your handler has not retrieved all the required parameters. If additional
  4520. required parameters exist, then your handler should immediately return an error.
  4521. If the attribute does not exist, then the Apple event does not contain any more
  4522. required parameters. 
  4523.  
  4524. Listing 6-11 shows a function that checks for a keyMissedKeywordAttr attribute.
  4525. A handler calls this function after getting all the required parameters it knows
  4526. about from an Apple event.
  4527.  
  4528. ¿ Listing 6-11   A function that checks for a keyMissedKeywordAttr attribute
  4529.  
  4530. FUNCTION MyGotRequiredParams (theAppleEvent: AppleEvent) : OSErr;
  4531. VAR
  4532.    returnedType:   DescType;
  4533.    actualSize:     Size;
  4534.    myErr:          OSErr;
  4535. BEGIN
  4536.    myErr := AEGetAttributePtr (theAppleEvent, keyMissedKeywordAttr, 
  4537.                                typeWildCard, returnedType, NIL, 0, 
  4538.                                actualSize);
  4539.    IF myErr = errAEDescNotFound THEN  {you got all the required }
  4540.                                       { parameters}
  4541.       MyGotRequiredParams := noErr
  4542.    ELSE IF myErr = noErr THEN {you missed a required parameter}
  4543.       MyGotRequiredParams := errAEEventNotHandled
  4544.    ELSE {the call to AEGetAttributePtr failed}
  4545.       MyGotRequiredParams := myErr;
  4546.   END;
  4547.  
  4548. The code in Listing 6-11 uses the AEGetAttributePtr function to get the
  4549. keyMissedKeywordAttr attribute. This attribute contains the first required
  4550. parameter, if any, that your handler didn’t retrieve. If AEGetAttributePtr
  4551. returns the errAEDescNotFound result code, the Apple event doesn’t contain a
  4552. keyMissedKeywordAttr attribute. If the Apple event doesn’t contain this
  4553. attribute, then your handler has extracted all of the required parameters. 
  4554.  
  4555. If the AEGetAttributePtr function returns noErr as the result code, then the
  4556. attribute does exist, meaning that your handler has not extracted all of the
  4557. required parameters. In this case, your handler should return an error and not
  4558. process the Apple event.
  4559.  
  4560. The first remaining required parameter is specified by the data of the
  4561. keyMissedKeywordAttr attribute. If you want this data returned, specify a buffer
  4562. to hold the data. Otherwise, specify NIL as the buffer and 0 as the size of the
  4563. buffer. If you specify a buffer to hold the data, you can check the value of the
  4564. actualSize parameter to see if the data is larger than the buffer you allocated.
  4565. _______________________________________________________________________________
  4566.  
  4567. æKY Replying…to…an…Apple…Event
  4568. æC »Replying to an Apple Event                                     The Apple Event Manager
  4569. _______________________________________________________________________________
  4570.  
  4571. Your handler routine for a particular Apple event is responsible for performing
  4572. the action requested by the Apple event, and can optionally return data in a
  4573. reply Apple event. The Apple Event Manager passes a default reply Apple event to
  4574. your handler. The default reply Apple event has no parameters when it is passed
  4575. to your handler. Your handler can add parameters to the reply Apple event. If
  4576. the client application requested a reply, the Apple Event Manager returns the
  4577. reply Apple event to the client. 
  4578.  
  4579. The reply Apple event is identified by the kCoreEventClass event class and by
  4580. the kAEAnswer event ID.
  4581.  
  4582. When your handler finishes processing an Apple event, it returns a result code
  4583. to AEProcessAppleEvent. The AEProcessAppleEvent function returns this result
  4584. code as its function result. If your handler returns a nonzero result code, the
  4585. Apple Event Manager also returns this result code to the client application by
  4586. putting the result code into a keyErrorNumber parameter for the reply Apple
  4587. event. The client can check for the existence of this parameter to determine
  4588. whether the handler performed the requested action.
  4589.  
  4590. The client application specifies whether it wants a reply Apple event or not by
  4591. specifying flags (represented by constants) in the sendMode parameter of the
  4592. AESend function.
  4593.  
  4594. If the client specifies the kAEWaitReply flag in the sendMode parameter, the
  4595. AESend function does not return until the timeout expires or the server returns
  4596. a reply. When the server returns a reply, the reply parameter to AESend contains
  4597. the reply Apple event that your handler returned to the AEProcessAppleEvent
  4598. function.
  4599.  
  4600. If the client specified the kAEQueueReply flag, the client receives the reply
  4601. event in its normal processing of other events.
  4602.  
  4603. If the client specified the kAENoReply flag, your handler may return a reply
  4604. Apple event to AEProcessAppleEvent, but this reply is not returned to the
  4605. client.
  4606.  
  4607. Your handler routine should always set its function result to noErr if it
  4608. successfully handles the Apple event or to a nonzero result code if an error
  4609. occurs. The Apple Event Manager automatically adds any nonzero result code that
  4610. your handler returns to a keyErrorNumber parameter in the reply Apple event. In
  4611. addition to returning a result code, your handler can also return an error
  4612. string in the keyErrorString parameter of the reply Apple event. Your handler
  4613. should provide meaningful text in the keyErrorString parameter, so that the
  4614. client can display this string to the user if desired.
  4615.  
  4616. Listing 6-12 shows how to add the keyErrorString parameter to the reply Apple
  4617. event. See “Adding Parameters to an Apple Event” later in this chapter for a
  4618. description of the AEPutParamPtr function.
  4619.  
  4620. ¿ Listing 6-12   Adding the keyErrorString parameter to the reply Apple event
  4621.  
  4622. FUNCTION MyHandler (theAppleEvent: AppleEvent; reply: AppleEvent;
  4623.                     handlerRefcon: LongInt) : OSErr; 
  4624. VAR
  4625. myErr:   OSErr;
  4626. errStr:  Str255;
  4627. BEGIN
  4628.    {if an error occurs when handling an Apple event, set the }
  4629.    { function result and error string accordingly}
  4630. IF myErr <> noErr THEN
  4631.    BEGIN
  4632.    MyHandler := myErr;    {result code to be returned - the Apple Event }
  4633.                           { Manager adds this result code to the reply }
  4634.                           { Apple event as the keyErrorNumber parameter}
  4635.    {add error string parameter to the default reply}
  4636.    errStr := 'Reason why error occurred';
  4637.    myErr := AEPutParamPtr(reply, keyErrorString, typeChar, 
  4638.                           Ptr(@errStr[1]), length(errStr));
  4639.    Exit(MyHandler);
  4640.    END;
  4641. END;
  4642.  
  4643. If your handler needs to return data to the client, it can add parameters to the
  4644. reply Apple event. For example, Listing 6-13 shows how a handler for the
  4645. Multiply event (an imaginary Apple event that asks the server to multiply two
  4646. numbers) might return the results of the multiplication to the client.
  4647.  
  4648. ¿ Listing 6-13   Adding parameters to the reply Apple event
  4649.  
  4650. FUNCTION MyMultHandler (theAppleEvent: AppleEvent; reply: AppleEvent;
  4651.                         handlerRefcon: LongInt) : OSErr; 
  4652. VAR
  4653. myErr:               OSErr;
  4654. number1, number2:    LongInt;
  4655. replyResult:         LongInt;
  4656. actualSize:          Size;
  4657. returnedType:        DescType;
  4658. BEGIN
  4659.    {get the numbers to multiply from the parameters of the Apple event }
  4660.    { put the numbers in the number1 and number2 variables }
  4661.    { then perform the requested multiplication}
  4662. myErr := MyDoMultiply(theAppleEvent, number1, number2, replyResult);
  4663.  
  4664. {return the result of the multiplication in the reply Apple event}
  4665. IF myErr = noErr THEN
  4666.    BEGIN
  4667.    myErr := AEPutParamPtr(reply, keyDirectObject, typeLongInteger, 
  4668.                           @replyResult, SizeOf(replyResult));
  4669.    MyMultHandler := myErr;
  4670.    END;
  4671. {if an error occurs, set the function result and error string }
  4672. { accordingly, as shown in Listing 6-12}
  4673. END;
  4674. _______________________________________________________________________________
  4675.  
  4676. æKY Disposing…of…Apple…Event…Data…Structures
  4677. æC »Disposing of Apple Event Data Structures                       The Apple Event Manager
  4678. _______________________________________________________________________________
  4679.  
  4680. Whenever you use Apple Event Manager functions to create a descriptor record,
  4681. descriptor list, or Apple event record, the Apple Event Manager allocates memory
  4682. for these data structures. Likewise, when you extract a descriptor record by
  4683. using Apple Event Manager functions, the Apple Event Manager creates a copy of
  4684. the descriptor record for you to use.
  4685.  
  4686. Whenever you are done using a descriptor record or descriptor list that you have
  4687. created or extracted from an Apple event, you must dispose of the descriptor
  4688. record—and thereby deallocate the memory it uses—by calling the AEDisposeDesc
  4689. function.
  4690.  
  4691. Also, when you are done using the Apple event specified in the AESend function
  4692. and finished with the reply Apple event, you should dispose of their descriptor
  4693. records using the AEDisposeDesc function. You should dispose of them even if
  4694. AESend returns a nonzero result code.
  4695.  
  4696. Once you are done using them, you should dispose of any Apple event data
  4697. structures created or returned by these functions:
  4698.  
  4699.    AECreateAppleEvent                 AECreateList
  4700.    AEGetNthDesc                             AECreateDesc
  4701.    AEGetKeyDesc                              AEGetParamDesc
  4702.    AECoerceDesc                               AEGetAttributeDesc
  4703.    AECoercePtr                                  AEDuplicateDesc
  4704.    AEGetKeyDesc
  4705.  
  4706. Even if you add a descriptor record to an Apple event (for example, when you
  4707. create a descriptor record by calling AECreateDesc and then put a copy of it
  4708. into a parameter of an Apple event by calling AEPutParamDesc), you’re still
  4709. responsible for disposing of the original descriptor record.
  4710.  
  4711. In one case, the Apple Event Manager does take care of disposing of the Apple
  4712. event data structures for you: when your handler returns to AEProcessAppleEvent,
  4713. the Apple Event Manager disposes of the Apple event and the reply Apple event.
  4714. Note that your handler is still responsible for disposing of any Apple event
  4715. data structures created when extracting data from the Apple event. The Apple
  4716. event and reply Apple event that your handler receives are only copies of the
  4717. originals. The client application is responsible for disposing of the original
  4718. data structures.
  4719. _______________________________________________________________________________
  4720.  
  4721. æKY Interacting…With…the…User
  4722. æC »Interacting With the User                                      The Apple Event Manager
  4723. _______________________________________________________________________________
  4724.  
  4725. When your application receives an Apple event, it may need to interact with the
  4726. user. For example, your application may need to display a dialog box asking for
  4727. additional input or confirmation from the user. You must make sure that your
  4728. application is in the foreground before interacting with the user. To do this,
  4729. use the AEInteractWithUser function before actually interacting with the user.
  4730. The AEInteractWithUser function checks the user interaction preferences set by
  4731. the client application and the server application and, if user interaction is
  4732. allowed, brings your application to the front (either directly or by posting a
  4733. notification request) if it is not already in the front.
  4734.  
  4735. If both the client and server applications allow user interaction,
  4736. AEInteractWithUser usually posts a notification request; AEInteractWithUser
  4737. brings the server to the front after the user responds to the notification
  4738. request. The AEInteractWithUser function can also bring the server application
  4739. directly to the front—but only when doing so is in accordance with the principle
  4740. of user control and if the client allows it.
  4741.  
  4742. Both the client and server specify their preferences for user interaction: the
  4743. client specifies whether the server should be allowed to interact with the user,
  4744. and the server specifies when it will allow user interaction while processing an
  4745. Apple event. 
  4746.  
  4747. An application that sends an Apple event indicates its preferences for how the
  4748. server application should interact with the user by setting various flags in the
  4749. sendMode parameter to AESend. The Apple Event Manager translates these flags
  4750. into the corresponding flags in the keyInteractLevelAttr attribute of the Apple
  4751. event, and sets them.
  4752.  
  4753. The server application sets its preferences by using the AESetInteractionAllowed
  4754. function. This function lets your application specify whether it allows
  4755. interaction with the user as a result of receiving an Apple event from itself;
  4756. from itself and other processes on the local machine; or from itself, local
  4757. processes, and processes from another computer on the network.
  4758.  
  4759. Your application calls the AEInteractWithUser function before interacting with
  4760. the user. If AEInteractWithUser returns the noErr result code, then your
  4761. application is currently in the front and your application is free to interact
  4762. with the user. If AEInteractWithUser returns the errAENoUserInteraction result
  4763. code, then the conditions didn’t allow user interaction and your application
  4764. should not interact with the user. 
  4765.  
  4766. The client application sets user interaction preferences by setting flags in the
  4767. sendMode parameter to the AESend function. The Apple Event Manager automatically
  4768. adds the specified flags to the keyInteractLevelAttr attribute of the Apple
  4769. event. These flags are represented by constants and are described here.
  4770.  
  4771. Flag                                      Description
  4772.  
  4773. kAENeverInteract            The server application should never interact with
  4774. the 
  4775.                                               user in response to this Apple
  4776.                                               event. If this flag is set, 
  4777.                                               AEInteractWithUser does not bring
  4778.                                               the server application 
  4779.                                               to the foreground (this is the
  4780.                                               default when an Apple 
  4781.                                               event is sent to a remote
  4782.                                               application).
  4783.  
  4784. kAECanInteract                 The server application can interact with the user
  4785. in 
  4786.                                                response to this Apple event—by
  4787.                                                convention, if the user 
  4788.                                                needs to supply information to
  4789.                                                the server. If this flag is 
  4790.                                                set and the server allows
  4791.                                                interaction, 
  4792.                                                AEInteractWithUser brings the
  4793.                                                server application to the 
  4794.                                                foreground (this is the default
  4795.                                                when an Apple event is 
  4796.                                                sent to a local application).
  4797.  
  4798. kAEAlwaysInteract           The server application can interact with the user in
  4799.  
  4800.                                                response to this Apple event—by
  4801.                                                convention, even if no 
  4802.                                                information is needed from the
  4803.                                                user. If this flag is set and 
  4804.                                                the server allows interaction,
  4805.                                                AEInteractWithUser brings 
  4806.                                                the server application to the
  4807.                                                foreground. The Apple 
  4808.                                                Event Manager does not
  4809.                                                distinguish between this flag and
  4810.                                                the kAECanInteract
  4811.                                                flag—distinguishing between them
  4812.                                                is
  4813.                                                the responsibility of the server
  4814.                                                application.
  4815.  
  4816. If the client application doesn’t specify any of the user interface flags, the
  4817. Apple Event Manager sets either the kAENeverInteract or the kAECanInteract flag
  4818. in the keyInteractLevelAttr attribute of the Apple event, depending on the
  4819. location of the server application. If the server application is on a remote
  4820. computer, the Apple Event Manager sets the kAENeverInteract flag as the default.
  4821. If the server application is on the local computer, the Apple Event Manager sets
  4822. the kAECanInteract flag as the default.
  4823.  
  4824. In addition, the client application can set another flag in the sendMode
  4825. parameter to AESend to request that the Apple Event Manager immediately bring
  4826. the server application to the front (instead of posting a notification
  4827. request)—if user interaction is allowed and if the user interface guidelines
  4828. permit. 
  4829.  
  4830. Flag                                        Description
  4831.  
  4832. kAECanSwitchLayer          If both the client and server allow interaction and
  4833. this 
  4834.                                                 flag is set, AEInteractWithUser
  4835.                                                 brings the server directly 
  4836.                                                 to the foreground if adherence
  4837.                                                 to the principle of user 
  4838.                                                 control allows. If the action
  4839.                                                 would be contrary to this 
  4840.                                                 principle, AEInteractWithUser
  4841.                                                 uses the Notification 
  4842.                                                 Manager to request that user
  4843.                                                 bring the server application 
  4844.                                                 to the foreground. If both the
  4845.                                                 client and server allow    
  4846.                                                 interaction and this flag is not
  4847.                                                 set, AEInteractWithUser 
  4848.                                                 always uses the Notification
  4849.                                                 Manager to request that the 
  4850.                                                 user bring the server
  4851.                                                 application to the foreground.
  4852.  
  4853. When a server application calls AEInteractWithUser, the function first checks to
  4854. see if the kAENeverInteract flag in the keyInteractLevelAttr attribute of the
  4855. Apple event is set. (The Apple Event Manager sets this attribute according to
  4856. the flags specified in the sendMode parameter of AESend.) If the
  4857. kAENeverInteract flag is set, AEInteractWithUser immediately returns the
  4858. errAENoUserInteraction result code. If the client specified kAECanInteract or
  4859. kAEAlwaysInteract, AEInteractWithUser checks the server’s preferences for user
  4860. interaction.
  4861.  
  4862. The server sets its user interaction preferences by using the
  4863. AESetInteractionAllowed function. You use this function to tell the Apple Event
  4864. Manager the processes for which your application is willing to interact with the
  4865. user.
  4866.  
  4867. myErr := AESetInteractionAllowed(level);
  4868.  
  4869. The level parameter is of type AEInteractAllowed. 
  4870.  
  4871.    TYPE  AEInteractAllowed = (kAEInteractWithSelf, kAEInteractWithLocal, 
  4872.                               kAEInteractWithAll);
  4873.  
  4874. You can specify one of these values for the interaction level.
  4875.  
  4876. Flag                                         Description
  4877.  
  4878. kAEInteractWithSelf          User interaction with your server application in 
  4879.                                                  response to an Apple event may
  4880.                                                  be allowed only when 
  4881.                                                  the client application is your
  4882.                                                  own application—that is, 
  4883.                                                  only when your application is
  4884.                                                  sending the Apple event 
  4885.                                                  to itself.
  4886.  
  4887. kAEInteractWithLocal       User interaction with your server application in 
  4888.                                                  response to an Apple event may
  4889.                                                  be allowed only if the 
  4890.                                                  client application is on the
  4891.                                                  same computer as your 
  4892.                                                  application; this is the
  4893.                                                  default if the 
  4894.                                                  AESetInteractionAllowed
  4895.                                                  function is not used.
  4896.  
  4897. kAEInteractWithAll          User interaction with your server application in
  4898. response
  4899.                                                 to an Apple event may be allowed
  4900.                                                 for any client 
  4901.                                                 application on any computer.
  4902.  
  4903. If the server application does not set the user interaction level,
  4904. AEInteractWithUser uses kAEInteractWithLocal as the value.
  4905.  
  4906. If the application sent itself an Apple event (that is, the application is both
  4907. the client and the server), AEInteractWithUser always allows user interaction.
  4908. If the client application is a process on the local machine, and the server set
  4909. the interaction level to the kAEInteractWithLocal or kAEInteractWithAll flag,
  4910. then AEInteractWithUser allows user interaction. If the client is a process on a
  4911. remote computer on the network, AEInteractWithUser allows user interaction only
  4912. if the server specified the kAEInteractWithAll flag for the interaction level.
  4913. In all other cases, AEInteractWithUser does not allow user interaction.
  4914.  
  4915. When AEInteractWithUser allows user interaction (based on the client and
  4916. server’s preferences), AEInteractWithUser brings the server application to the
  4917. front—either directly or after the user responds to a notification request—and
  4918. then returns a noErr result code. 
  4919.  
  4920. If AEInteractWithUser cannot bring the server application to the front within
  4921. the specified timeout value, AEInteractWithUser returns the errAETimeout result
  4922. code.
  4923.  
  4924. Your application may want to provide the user with a method of setting the
  4925. interaction level. For example, some users may not want to be interrupted while
  4926. background processing of an Apple event occurs, or they may not want to respond
  4927. to dialog boxes when your application is handling Apple events sent from another
  4928. computer.
  4929.  
  4930. Listing 6-14 illustrates the use of the AEInteractWithUser function. You call
  4931. this function before your application displays a dialog box or otherwise
  4932. interacts with the user when processing an Apple event. You specify a timeout
  4933. value, a pointer to a Notification Manager record, and the address of an idle
  4934. function as parameters to AEInteractWithUser.
  4935.  
  4936. ¿ Listing 6-14   Using the AEInteractWithUser function
  4937.  
  4938. myErr := AEInteractWithUser (kAEDefaultTimeOut, NIL, @MyIdleFunction);
  4939. IF myErr <> noErr THEN
  4940.    {the attempt to interact failed, do any error handling}
  4941.    DoError(myErr)
  4942. ELSE
  4943.    {interact with the user by displaying a dialog box }
  4944.    { or by interacting in any other way that is necessary}
  4945.  
  4946. You can set a timeout value, in ticks, in the first parameter to
  4947. AEInteractWithUser. Use the kAEDefaultTimeout constant if you want the Apple
  4948. Event Manager to use a default value for the timeout value. The Apple Event
  4949. Manager uses a timeout value of about one minute if you specify this constant.
  4950. You can also specify the kNoTimeOut constant if your application is willing to
  4951. wait an indefinite amount of time for a response from the user. Usually you
  4952. should provide a timeout value, so that your application can complete processing
  4953. of the Apple event in a reasonable amount of time.
  4954.  
  4955. You can provide a pointer to a Notification Manager record in the second
  4956. parameter, or you can specify NIL to use the default record provided by
  4957. AEInteractWithUser. The AEInteractWithUser function only uses a Notification
  4958. Manager record when user interaction is allowed and the kAECanSwitchLayer flag
  4959. in the keyInteractLevelAttr attribute is not set.
  4960.  
  4961. The last parameter to AEInteractWithUser specifies an idle function provided by
  4962. your application. Your idle function should handle any update events, null
  4963. events, operating-system events, or activate events while your application is
  4964. waiting to be brought to the front. See “Writing an Idle Function” later in this
  4965. chapter for more information.
  4966. _______________________________________________________________________________
  4967.  
  4968. æKY Creating…an…Apple…Event
  4969. æC »Creating an Apple Event                                        The Apple Event Manager
  4970. _______________________________________________________________________________
  4971.  
  4972. You create an Apple event by using the AECreateAppleEvent function. You specify
  4973. the event class and event ID, the target address, the return ID, and the
  4974. transaction ID to the function. The AECreateAppleEvent function creates and
  4975. returns an Apple event with the attributes set as your application requested.
  4976. You should not directly manipulate the contents of the Apple event; rather, use
  4977. Apple Event Manager functions to add additional attributes or parameters to it.
  4978.  
  4979. This example creates a Multiply event using the AECreateAppleEvent function. You
  4980. specify the event class, the event ID, the address of the server application, a
  4981. return ID, a transaction ID, and a buffer to store the returned Apple event as
  4982. parameters to AECreateAppleEvent. 
  4983.  
  4984. myErr := AECreateAppleEvent(kArithmeticClass, kMultEventID,
  4985.                             targetAddress, kAutoGenerateReturnID,
  4986.                             kAnyTransactionID,theAppleEvent);
  4987.  
  4988. The event class here is identified by the kArithmeticClass constant and
  4989. specifies that this event belongs to a specific class of Apple events for
  4990. arithmetic operations. The event ID specifies the particular Apple event within
  4991. the class; in this case, an Apple event to perform multiplication.
  4992.  
  4993. You specify the target of the Apple event in the third parameter to
  4994. AECreateAppleEvent. The target address can identify an application on the local
  4995. computer or another computer on the network. You can specify the address using a
  4996. target ID record or session ID. For processes on the local computer, you can
  4997. also use a process serial number or application signature to specify the
  4998. address. See “Specifying a Target Address” later in this chapter for more
  4999. information. 
  5000.  
  5001. You specify the return ID of the Apple event in the fourth parameter. The return
  5002. ID provides a way to associate this Apple event to the server’s reply. The
  5003. AECreateAppleEvent function assigns the specified return ID value to the
  5004. keyReturnIDAttr attribute of the Apple event. If a server returns an Apple event
  5005. in response to this event, the server should use the same return ID. When you
  5006. receive an Apple event, you can check the keyReturnIDAttr attribute to determine
  5007. whether the event is a response to an outstanding Apple event. You can use the
  5008. kAutoGenerateReturnID constant to request that the Apple Event Manager generate
  5009. a return ID that is unique to this session for the Apple event.
  5010.  
  5011. The fifth parameter specifies the transaction ID attribute of the Apple event. A
  5012. transaction refers to a sequence of Apple events that are sent back and forth
  5013. between the client and server applications, beginning with the client’s initial
  5014. request for a service. All Apple events that are part of one transaction must
  5015. have the same transaction ID.
  5016.  
  5017. You can use a transaction ID to indicate that an Apple event is one of a
  5018. sequence of Apple events related to a single transaction. The kAnyTransactionID
  5019. constant indicates that the Apple event is not part of a transaction.
  5020.  
  5021. The AECreateAppleEvent function creates an Apple event with only the specified
  5022. attributes and no parameters. To add parameters or additional attributes, use
  5023. other Apple Event Manager functions.
  5024. _______________________________________________________________________________
  5025.  
  5026. æKY Adding…Parameters…to…an…Apple…Event
  5027. æC »Adding Parameters to an Apple Event                            The Apple Event Manager
  5028. _______________________________________________________________________________
  5029.  
  5030. You can use the AEPutParamPtr or AEPutParamDesc functions to add parameters to
  5031. an Apple event. When you use either of these functions, the Apple Event Manager
  5032. adds the specified parameter to the Apple event. 
  5033.  
  5034. Use the AEPutParamPtr function when you want to add data specified in a buffer
  5035. as the parameter of an Apple event. You specify the Apple event, the keyword of
  5036. the parameter to add, the descriptor type, a buffer that contains the data, and
  5037. the size of this buffer as parameters to the AEPutParamPtr function. The
  5038. AEPutParamPtr function creates the descriptor record and adds the parameter to
  5039. the Apple event.
  5040.  
  5041. For example, this code adds a parameter to the Multiply event using the
  5042. AEPutParamPtr function.
  5043.  
  5044. CONST  keyOperand1 = 'OPN1';
  5045. VAR
  5046. number1:        Integer;
  5047. theAppleEvent:  AppleEvent;
  5048.  
  5049. number1 := 10;
  5050. myErr := AEPutParamPtr(theAppleEvent, keyOperand1, typeInteger,
  5051.                        @number1, SizeOf(number1));
  5052.  
  5053. In this example, the Apple Event Manager adds the parameter containing the first
  5054. number to the specified Apple event.
  5055.  
  5056. Use the AEPutParamDesc function to add data specified in a descriptor record to
  5057. an Apple event. The descriptor record you specify must have been previously
  5058. created using the AECreateDesc or AEDuplicateDesc function. 
  5059.  
  5060. You specify the descriptor type, a buffer that contains the data, and the size
  5061. of this buffer as parameters to the AECreateDesc function. The AECreateDesc
  5062. function returns the descriptor record that describes the data.
  5063.  
  5064. This example creates a descriptor record for the second parameter of the
  5065. Multiply event:
  5066.  
  5067. VAR
  5068. number2:         Integer;
  5069. multParam2Desc:  AEDesc;
  5070.  
  5071. number2 := 8;
  5072. myErr := AECreateDesc(typeInteger, @number2, SizeOf(number2),
  5073.                       multParam2Desc);
  5074.  
  5075. In this example, the AECreateDesc function creates a descriptor record with the
  5076. typeInteger descriptor type and the data identified in the number2 variable.
  5077.  
  5078. Once you have created a descriptor record, you can use AEPutParamDesc to add the
  5079. data to a parameter of an Apple event. You specify the Apple event to add the
  5080. parameter to, the keyword of the parameter, and the descriptor record of the
  5081. parameter as parameters to the AEPutParamDesc function.
  5082.  
  5083. This example adds a second parameter to the Multiply event using the
  5084. AEPutParamDesc function.
  5085.  
  5086. CONST  keyOperand2 = 'OPN2';
  5087.  
  5088. myErr := AEPutParamDesc(theAppleEvent, keyOperand2, multParam2Desc);
  5089.  
  5090. This example adds the keyOperand2 keyword and the descriptor record created in
  5091. the previous example as the second parameter to the specified Apple event.
  5092.  
  5093. The previous examples showed how to add parameters to the imaginary Multiply
  5094. event. After adding parameters to an Apple event, you can send the Apple event
  5095. using the AESend function. See “Sending an Apple Event” later in this chapter
  5096. for information on using this function.
  5097. _______________________________________________________________________________
  5098.  
  5099. æKY Specifying…a…Target…Address
  5100. æC »Specifying a Target Address                                    The Apple Event Manager
  5101. _______________________________________________________________________________
  5102.  
  5103. When you create an Apple event, you must specify the address of the target. The
  5104. target address identifies the particular application or process that you want to
  5105. send the Apple event to. You can send Apple events to applications on the local
  5106. machine or on remote computers on the network. 
  5107.  
  5108. These are the descriptor types that identify the four methods of addressing an
  5109. Apple event.
  5110.  
  5111.    typeApplSignature                 The application signature of the target
  5112.  
  5113.    typeSessionID                          The session ID of the target
  5114.  
  5115.    typeTargetID                             The target ID record of the target
  5116.  
  5117.    typeProcessSerialNumber     The process serial number of the target
  5118.  
  5119. To address an Apple event to a target on a remote computer on the network, you
  5120. must use either the typeSessionID or typeTargetID descriptor type.
  5121.  
  5122. If your application sends an Apple event to itself, it should address the Apple
  5123. event using a process serial number. Use the kCurrentProcess constant to specify
  5124. the process serial number of your application. This is the fastest way for your
  5125. application to send an Apple event to itself.
  5126.  
  5127. You can use any of the four address types when sending an Apple event to another
  5128. application on the local computer. To allow the user to choose the target of an
  5129. Apple event, use the PPCBrowser function. The PPCBrowser function presents a
  5130. standard user interface for choosing a target application, much as the Standard
  5131. File Package provides a standard user interface for opening and saving files.
  5132.  
  5133. The PPCBrowser function returns information about the application the user chose
  5134. in a targetID record. (Listing 6-16 later in this section shows how to use the
  5135. PPCBrowser function to let the user choose a target.) 
  5136.  
  5137. The Event Manager chapter in this volume describes all four types of addresses.
  5138. Your application can also use another address type, if it also provides a
  5139. coercion handler that coerces the address type into one of the four address
  5140. types that the Apple Event Manager recognizes. See “Writing and Installing
  5141. Coercion Handlers” later in this chapter for more information.
  5142.  
  5143. You specify the address using an address descriptor record (a descriptor record
  5144. of data type AEAddressDesc). You must create a descriptor record of this type
  5145. and then supply the address descriptor record as a parameter to the
  5146. AECreateAppleEvent function.
  5147.  
  5148. You can use the AECreateDesc function to add any of the four target addresses to
  5149. an address descriptor record. Listing 6-15 shows four possible ways to create an
  5150. address, each using a different address type.
  5151.  
  5152. ¿ Listing 6-15   Creating a target address
  5153.  
  5154. PROCEDURE SetTargetAddresses(VAR targetAddress1, targetAddress2,
  5155.                              targetAddress3, targetAddress4:
  5156.                              AEAdressDesc; toTargetID: TargetID; 
  5157.                              thePSN: ProcessSerialNumber; 
  5158.                              theSignature: OSType; 
  5159.                              theSessionID: sessionID);
  5160. VAR
  5161. myErr: OSErr;
  5162.  
  5163. BEGIN
  5164. myErr := AECreateDesc(typeTargetID, @toTargetID, SizeOf(toTargetID),
  5165.                       targetAddress1);
  5166. myErr := AECreateDesc(typeProcessSerialNumber, @thePSN, SizeOf(thePSN),
  5167.                       targetAddress2);
  5168. myErr := AECreateDesc(typeApplSignature, @theSignature, 
  5169.                       SizeOf(theSignature), targetAddress3);
  5170. myErr := AECreateDesc(typeSessionID, @theSessionID, SizeOf(theSessionID),
  5171.                       targetAddress4);
  5172. END;
  5173.  
  5174. You specify the descriptor type for the address, a pointer to the buffer
  5175. containing the address, and the size of the buffer to the AECreateDesc function
  5176. to create an address descriptor record. The AECreateDesc function returns an
  5177. address descriptor record with the specified characteristics.
  5178.  
  5179. After creating an address, you can specify the address in the AECreateAppleEvent
  5180. function. See “Creating an Apple Event” earlier in this chapter for an example
  5181. using the AECreateAppleEvent function. 
  5182.  
  5183. When you specify an address to the AECreateAppleEvent function, the Apple Event
  5184. Manager stores the address in the keyAddressAttr attribute of the Apple event. 
  5185.  
  5186. You can use the PPCBrowser function to create a target ID. Listing 6-16 shows
  5187. how to use the information returned from the PPCBrowser function to create a
  5188. target ID. You can then use AECreateDesc to create the address descriptor record
  5189. for an Apple event.
  5190.  
  5191. ¿ Listing 6-16   Specifying a target address in an Apple event
  5192.  
  5193. FUNCTION GetTargetAddress(myPrompt: Str255; myAppStr: Str255;
  5194.                           VAR myPortInfo: PortInfoRec; 
  5195.                           VAR targetAddress: AEAddressDesc; 
  5196.                           VAR toTargetID: targetID) : OSErr;
  5197.  
  5198. BEGIN      {use PPCBrowser to let user choose the target}
  5199.    myErr := PPCBrowser(myPrompt, myAppStr, FALSE, toTargetID.location, 
  5200.                        myPortInfo, NIL, '');
  5201.    IF myErr <> noErr THEN
  5202.       DoError(myErr);
  5203.    ELSE 
  5204.    BEGIN
  5205.    toTargetID.name := myPortInfo.name;
  5206.             {create the descriptor record for the target address}
  5207.    myErr := AECreateDesc(typeTargetID, @toTargetID, 
  5208.                          SizeOf(toTargetID), targetAddress);
  5209.    IF myErr <> noErr THEN
  5210.       DoError(myErr);
  5211.    END;
  5212.    GetTargetAddress := myErr;
  5213. END;
  5214.  
  5215. See the Program-to-Program Communications Toolbox chapter for more information
  5216. on using the PPCBrowser function.
  5217. _______________________________________________________________________________
  5218.  
  5219. æKY Sending…an…Apple…Event
  5220. æC »Sending an Apple Event                                         The Apple Event Manager
  5221. _______________________________________________________________________________
  5222.  
  5223. To send an Apple event, you first create an Apple event, add parameters and
  5224. attributes to the Apple event, and then use the AESend function to send it. 
  5225.  
  5226. When you send an Apple event, you specify various options to indicate how the
  5227. server should handle the Apple event. You request a user interaction level from
  5228. the server and specify whether the server can directly switch to the foreground
  5229. if user interaction is needed, whether your application is willing to wait for a
  5230. reply Apple event, whether reconnection is allowed, and whether your application
  5231. wants a return receipt for the Apple event.
  5232.  
  5233. You specify these options in the sendMode parameter to AESend. Here are the
  5234. constants that represent these options.
  5235.  
  5236.    CONST  kAENoReply         = $00000001;       {client doesn't want reply}
  5237.           kAEQueueReply      = $00000002;       {client wants to receive }
  5238.                                                 { reply in event queue}
  5239.           kAEWaitReply       = $00000003;       {client wants to receive }
  5240.                                                 { the reply directly and }
  5241.                                                 { will give up the processor}
  5242.           kAENeverInteract   = $00000010;       {server should not }
  5243.                                                 { interact with user}
  5244.           kAECanInteract     = $00000020;       {server can interact }
  5245.                                                 { with user when needed}
  5246.           kAEAlwaysInteract  = $00000030;       {server can always }
  5247.                                                 { interact with user}
  5248.           kAECanSwitchLayer  = $00000040;       {interaction may directly }
  5249.                                                 { bring server to the front}
  5250.           kAEDontReconnect   = $00000080;       {if error, don't reconnect}
  5251.           kAEWantReceipt     = nReturnReceipt;  {client wants a return }
  5252.                                                 { receipt}
  5253.  
  5254. If your application wants a reply Apple event, specify the kAEQueueReply or
  5255. kAEWaitReply flag. If your application wants to receive the reply Apple event in
  5256. its event queue, use kAEQueueReply. If your application wants to receive the
  5257. reply Apple event in the reply parameter of AESend and is willing to give up the
  5258. processor while waiting for the reply, use kAEWaitReply. If your application
  5259. does not want a reply Apple event and does not need to wait for the server to
  5260. handle the Apple event, specify kNoReply. 
  5261.  
  5262. In most cases, your application should use kAEWaitReply or kAENoReply. You
  5263. should not use kAEQueueReply if your application is sending an Apple event to
  5264. itself.
  5265.  
  5266. If your application specifies kAENoReply or kAEQueueReply, the AESend function
  5267. returns immediately after using the Event Manager to send the event. In this
  5268. case, a noErr result code from AESend indicates that the Apple event was
  5269. successfully sent by the Event Manager; it does not mean that the server
  5270. accepted or handled the Apple event. 
  5271.  
  5272. Also, the reply parameter to AESend does not contain valid data on return from
  5273. AESend if your application specifies kAENoReply or kAEQueueReply. The kAENoReply
  5274. flag indicates that the Apple Event Manager will not return the reply Apple
  5275. event to your application. The kAEQueueReply flag indicates that your
  5276. application wants to receive the reply in its event queue rather than through
  5277. the reply parameter of AESend.
  5278.  
  5279. If your application specifies kAEWaitReply, the Apple Event Manager uses the
  5280. Event Manager to send the event. The Apple Event Manager then calls the
  5281. WaitNextEvent function on behalf of your application, causing your application
  5282. to yield the processor. This gives the server application a chance to receive
  5283. and handle the Apple event. Your application continues to yield the processor
  5284. until the server handles the Apple event or the request times out.
  5285.  
  5286. You use one of the three flags—kAENeverInteract, kAECanInteract, or
  5287. kAEAlwaysInteract—to specify whether the server should interact with the user
  5288. when handling the Apple event. Specify kAENeverInteract if the server should not
  5289. interact with the user when handling the Apple event. You might specify this
  5290. constant if you don’t want the user to be interrupted while the server is
  5291. handling the Apple event.
  5292.  
  5293. Use the kAECanInteract flag if the server should interact with the user when
  5294. necessary—for example, if the user needs to supply information to the server.
  5295. Use the kAEAlwaysInteract flag if the server should interact with the user even
  5296. when no information is needed from the user. Note that it is the responsibility
  5297. of the server and client applications to agree on how to interpret the
  5298. kAEAlwaysInteract flag. 
  5299.  
  5300. If the client application does not set any one of the user interaction flags,
  5301. the Apple Event Manager sets a default, depending on the location of the target
  5302. of the Apple event. If the server application is on a remote computer, the Apple
  5303. Event Manager sets the kAENeverInteract flag as the default. If the target of
  5304. the Apple event is on the local computer, the Apple Event Manager sets the
  5305. kAECanInteract flag as the default.
  5306.  
  5307. The server application should call AEInteractWithUser if it needs to interact
  5308. with the user. If user interaction is allowed, the Apple Event Manager brings
  5309. the server to the front if it is not already the foreground process. If the
  5310. kAECanSwitchLayer flag is set and the principle of user control permits, the
  5311. Apple Event Manager directly brings the server application to the front. If the
  5312. action is contrary to the principle of user control, the Apple Event Manager
  5313. posts a notification request to inform the user to bring the server application
  5314. to the front. 
  5315.  
  5316. You should specify the kAECanSwitchLayer flag only when the client and server
  5317. applications reside on the same computer. In general, you should not set this
  5318. flag if it would be confusing or inconvenient to the user for the server
  5319. application to unexpectedly come to the front.
  5320.  
  5321. Specify the kAEDontReconnect flag if the Apple Event Manager should not
  5322. reconnect if it receives a session closed error from the PPC Toolbox. If you
  5323. don’t set this flag, the Apple Event Manager automatically attempts to reconnect
  5324. and reestablish the session.
  5325.  
  5326. Specify the kAEWantReceipt flag if your application wants notification that the
  5327. server did not accept the Apple event. If you specify this flag, the AESend
  5328. function returns the errAEEventNotHandled result code if the server did not
  5329. accept the Apple event.
  5330.  
  5331. Listing 6-17 illustrates how to send a Multiply event (an imaginary Apple event
  5332. for multiplying two long integers). It first creates an Apple event, adds
  5333. parameters containing the numbers to multiply, then sends it, specifying various
  5334. options. It also illustrates how to handle the reply Apple event that contains
  5335. the result.
  5336.  
  5337.    Note: If you want to send Apple events, your application must also handle the
  5338.    required Apple events. See “Handling the Required Apple Events” earlier in
  5339.    this 
  5340.    chapter for information on how to support the required Apple events.
  5341.  
  5342. ¿ Listing 6-17   Sending an Apple event
  5343.  
  5344. FUNCTION MySendMultiplyEvent (serverAddress: AEAddressDesc;
  5345.                               firstOperand: LongInt; secondOperand:
  5346.                               LongInt; replyResultLongInt: LongInt)
  5347.                               : OSErr;
  5348. CONST
  5349. kArithmeticClass    =  'ARTH';      {event class for arithmetic }
  5350.                                     { Apple events}
  5351. kMultipyEventID     =  'MULT';      {event ID for Multiply event}
  5352. keyMultOperand1     =   'OPN1';     {keyword for first parameter }
  5353. keyMultOperand2     =   'OPN2';     {keyword for second parameter }
  5354.  
  5355. VAR
  5356. theAppleEvent:      AppleEvent;
  5357. reply:              AppleEvent;
  5358. returnedType:       DescType;
  5359. actualSize:         LongInt;
  5360. BEGIN
  5361.    myErr := AECreateAppleEvent(kArithmeticClass, kMultiplyEventID,
  5362.                                ServerAddress, kAutoGenerateReturnID,
  5363.                                kAnyTransactionID, theAppleEvent);
  5364.    IF myErr <> noErr THEN
  5365.       DoError(myErr); {failed to create the event}    
  5366.    {add the first operand}
  5367.     myErr := AEPutParamPtr(theAppleEvent, keyMultOperand1, 
  5368.                            typeLongInteger, @firstOperand, 
  5369.                            SizeOf(firstOperand));
  5370.    IF myErr <> noErr THEN
  5371.       DoError(myErr);   {failed to add first parameter - be sure to}
  5372.                         { dispose of the event before leaving routine}
  5373.    {add the second operand with the proper keyword}
  5374.    myErr := AEPutParamPtr(theAppleEvent, keyMultOperand2, 
  5375.                           typeLongInteger, @secondOperand, 
  5376.                           SizeOf(secondOperand));
  5377.    IF myErr <> noErr THEN
  5378.       DoError(myErr);   {Be sure to dispose of the event and first }
  5379.                         { parameter before leaving routine}
  5380.    myErr := AESend(theAppleEvent, reply, kAEWaitReply + kAENeverInteract,
  5381.                    kAENormalPriority, 120, @myIdleFunction, NIL);
  5382.    IF myErr = noErr THEN {Apple event successfully sent}
  5383.    BEGIN       {check if it was successfully handled }
  5384.                { get result code returned by the server’s handler}
  5385.        myErr := AEGetParamPtr(reply, keyErrorNumber, typeLongInteger, 
  5386.                               returnedType, @errNumber, 
  5387.                               Sizeof(errNumber) );
  5388.        IF (myErr = errAEDescNotFound) | (errNumber = noErr) THEN
  5389.           {If keyErrorNumber doesn’t exist or server returned noErr }
  5390.        BEGIN        { then the Apple event was successfully handled. }
  5391.                     { The reply Apple event contains the result in }
  5392.                     { the direct parameter}
  5393.            myErr := AEGetParamPtr(reply, keyDirectObject, typeInteger,
  5394.                                   returnedType, @replyResultLongInt, 
  5395.                                   SizeOf(replyResultLongInt), actualSize);
  5396.            MySendMultiplyEvent := noErr;    
  5397.            Exit(MySendMultiplyEvent);
  5398.        END;
  5399.        ELSE
  5400.        BEGIN      {server returned an error, so get error string}
  5401.           myErr := AEGetParamPtr(reply, keyErrorString, typeChar, 
  5402.                                  returnedType, @errStr, 
  5403.                                  Sizeof(errStr));
  5404.           IF myErr = noErr THEN
  5405.              MyDisplayError(errStr);
  5406.        END;
  5407.      END;
  5408.      ELSE
  5409.      BEGIN
  5410.      {either the Apple event wasn’t successfully dispatched, }
  5411.      { the request timed out, the user canceled, or other error} 
  5412.      END;
  5413.      END;
  5414. MySendMultiplyEvent := myErr;
  5415. END;
  5416.  
  5417. The code in Listing 6-17 first creates an Apple event with kArithmeticClass as
  5418. the event class and kMultipyEventID as the event ID. It also specifies the
  5419. server of the Apple event. See “Specifying a Target Address” in an earlier
  5420. section for information on various ways to specify a target address. See
  5421. “Creating Apple Events” earlier in this chapter for more information on how to
  5422. create an Apple event.
  5423.  
  5424. The Multiply event shown in Listing 6-17 contains two parameters, each of which
  5425. specifies a number to multiply. See “Adding Parameters to an Apple Event”
  5426. earlier in this chapter for examples of how to specify the parameters for the
  5427. AEPutParamPtr function. 
  5428.  
  5429. After adding the parameters to the event, the code uses AESend to send the
  5430. event. The first parameter to AESend specifies the Apple event to send—in this
  5431. example, the Multiply event. The next parameter specifies the reply Apple event.
  5432.  
  5433.  
  5434. This example specifies kAEWaitReply in the third parameter, indicating that the
  5435. client is willing to yield the processor for the specified timeout value (120
  5436. ticks, or 2 seconds). The kAENeverInteract flag indicates that the server should
  5437. not interact with the user when processing the Apple event. The Multiply event
  5438. is sent using normal priority, meaning it is placed at the end of the event
  5439. queue. You can specify the kAEHighPriority flag to place the event in the front
  5440. of the event queue. 
  5441.  
  5442. The next to last parameter specifies the address of an idle function. If you
  5443. specify kAEWaitReply you should provide an idle function. This function should
  5444. process any update events, null events, operating-system events, or activate
  5445. events that occur while your application is waiting for a reply.  See “Writing
  5446. an Idle Function” later in this chapter for sample code that shows an idle
  5447. function. 
  5448.  
  5449. The last parameter to AESend specifies a filter function. You can supply a
  5450. filter function to filter high-level events that your application might receive
  5451. while waiting for a reply Apple event. You can specify NIL for this parameter if
  5452. you do not need to filter high-level events while waiting for a reply. See
  5453. “Writing a Reply Filter Function” later in this chapter for more information. 
  5454.  
  5455. If AESend returns a noErr result code and your application specified
  5456. kAEWaitReply, you should first see whether a result code was returned from the
  5457. handler routine by checking the reply Apple event for the existence of the
  5458. parameter whose keyword is keyErrorNumber. If the keyErrorNumber parameter does
  5459. not exist or contains the noErr result code, you can use AEGetParamPtr to get
  5460. the parameter you’re interested in from the reply Apple event. 
  5461.  
  5462. The code in Listing 6-17 checks the function result of AESend. If AESend returns
  5463. noErr, the code then checks the replyErrorNumber parameter of the reply Apple
  5464. event to determine whether the server successfully handled the Apple event. If
  5465. this parameter exists and indicates an error occurred, then the code gets the
  5466. error string out of the keyErrorString parameter. Otherwise, the server
  5467. performed the request, and the reply Apple event contains the answer to the
  5468. multiplication request.
  5469.  
  5470. When you are done using the Apple event specified in the AESend function and
  5471. finished with the reply Apple event, you must dispose of their descriptor
  5472. records using the AEDisposeDesc function.
  5473. _______________________________________________________________________________
  5474.  
  5475. æKY Dealing…With…Timeouts
  5476. æC »Dealing With Timeouts                                          The Apple Event Manager
  5477. _______________________________________________________________________________
  5478.  
  5479. When your application calls AESend and chooses to wait for the server to handle
  5480. the Apple event, it can also specify the maximum amount of time that it is
  5481. willing to wait for a response. You can specify a timeout value in the timeout
  5482. parameter to AESend. You can either specify a particular length of time, in
  5483. ticks, that your application is willing to wait, or you can specify the
  5484. kNoTimeOut constant or the kAEDefaultTimeout constant. 
  5485.  
  5486. Use the kNoTimeOut constant to indicate that your application is willing to wait
  5487. forever for a response from the server. You should use this value only if your
  5488. application is guaranteed that the server will respond in a reasonable amount of
  5489. time. You should also implement a method of checking if the user wants to
  5490. cancel. The idle function that you specify as a parameter to AESend should check
  5491. the event queue for any instances of Command-period and immediately return TRUE
  5492. as its function result if it finds a request to cancel in the event queue.
  5493.  
  5494. Use the kAEDefaultTimeout constant if you want the Apple Event Manager to use a
  5495. default value for the timeout value. The Apple Event Manager uses a timeout
  5496. value of about one minute if you specify this constant.
  5497.  
  5498. Note that if you set the kAEWaitReply flag and the server doesn’t have a handler
  5499. for the Apple event, AESend returns immediately with the errAEEventNotHandled
  5500. result code.
  5501.  
  5502. If the server doesn’t respond within the length of time specified by the timeout
  5503. value, AESend returns the errAETimeOut result code. This result code does not
  5504. necessarily mean that the server failed to perform the requested action; it only
  5505. means that the server did not complete processing within the specified time. The
  5506. server might still be processing the Apple event, and it might still send a
  5507. reply.
  5508.  
  5509. If the server finishes processing the Apple event sometime after the time
  5510. specified in the timeout parameter has expired, it returns a reply Apple event
  5511. to AEProcessAppleEvent. The Apple Event Manager then returns the reply to the
  5512. client in the reply parameter that the client originally passed to the AESend
  5513. function. 
  5514.  
  5515. This means your application can continue to check the reply Apple event to see
  5516. if the server has responded, even after the time expires. If the server has not
  5517. yet sent the reply when the client attempts to extract data from the reply Apple
  5518. event, the Apple Event Manager functions return the errAEReplyNotArrived result
  5519. code. Once the reply Apple event returns from the server, the client can extract
  5520. the data in the reply.
  5521.  
  5522. Additionally, the server can determine the timeout value specified by the client
  5523. by examining the keyTimeoutAttr attribute in the Apple event. You can use the
  5524. value of this attribute as a rough estimate of how much time your handler has to
  5525. respond. You can assume that your handler has less time to respond than the
  5526. timeout value, because transmitting the Apple event uses some of the available
  5527. time, as does transmitting the reply Apple event back to the client.
  5528.  
  5529. If your handler needs more time than is specified in the keyTimeoutAttr
  5530. attribute, you can reset the timer by using the AEResetTimer function. This
  5531. function resets the timeout value of an Apple event to its starting value.
  5532.  
  5533. _______________________________________________________________________________
  5534.  
  5535. æKY Writing…an…Idle…Function
  5536. æC »Writing an Idle Function                                       The Apple Event Manager
  5537. _______________________________________________________________________________
  5538.  
  5539. This section describes how to write an idle function when using the AESend or
  5540. AEInteractWithUser functions.
  5541.  
  5542. When your application sends an Apple event, you can wait for the server
  5543. application to receive and finish handling the Apple event, or you can continue
  5544. processing. If your application chooses to continue processing, the AESend
  5545. function returns immediately after using the Event Manager to send the event. If
  5546. your application chooses to wait for the server to handle the event, the AESend
  5547. function does not return until either the server application finishes handling
  5548. the Apple event or a specified amount of time expires.
  5549.  
  5550. Your application specifies its preferences by setting flags in the sendMode
  5551. parameter to AESend. Your application can specify kAENoReply if it does not want
  5552. to receive a reply, kAEQueueReply if it wants to receive the reply in its event
  5553. queue, or kAEWaitReply if it wants the reply returned in the reply parameter of
  5554. AESend and is willing to give up the processor while waiting for the reply.
  5555.  
  5556. If your application specifies the kAEWaitReply flag, the AESend function calls
  5557. WaitNextEvent on behalf of your application. This yields the processor to other
  5558. processes, so that the server has an opportunity to receive and process the
  5559. Apple event sent by your application. While your application is waiting for a
  5560. reply, it cannot receive events unless it provides an idle function.
  5561.  
  5562. If your application provides a pointer to an idle function as a parameter to the
  5563. AESend function, AESend calls your idle function whenever an update event, null
  5564. event, operating-system event, or activate event is received for your
  5565. application. Your application can process high-level events that it receives
  5566. while waiting for a reply by providing a reply filter function. See the next
  5567. section, “Writing a Reply Filter Function,” for more information.
  5568.  
  5569. In a similar manner, when your application calls the AEInteractWithUser
  5570. function, your application can also yield the processor. If AEInteractWithUser
  5571. needs to post a notification request to bring your application to the front,
  5572. your application yields the processor until the user brings your application to
  5573. the front. To receive events while waiting for the user to bring your
  5574. application to the front, you must provide an idle function.
  5575.  
  5576. If your application provides a pointer to an idle function as a parameter to the
  5577. AEInteractWithUser function, AEInteractWithUser calls your idle function
  5578. whenever an update event, null event, operating-system event, or activate event
  5579. is received for your application.
  5580.  
  5581. An idle function must use this syntax:
  5582.  
  5583. FUNCTION MyIdleFunction (VAR theEventRecord: EventRecord;
  5584.                          VAR sleepTime: LongInt;
  5585.                          VAR mouseRgn: RgnHandle) : Boolean;
  5586.  
  5587. The parameter theEventRecord is the event record of the event to process. The
  5588. sleepTime parameter and mouseRgn parameters are values that your idle function
  5589. sets the first time it is called; thereafter they contain the values your
  5590. function set. Your idle function should return a Boolean value that indicates
  5591. whether your application wishes to continue waiting. Set the function result to
  5592. TRUE if your application is no longer willing to wait for a reply from the
  5593. server or for the user to bring the application to the front. Set the function
  5594. result to FALSE if your application is still willing to wait.
  5595.  
  5596. The first time your idle function is called, it receives a null event. At this
  5597. time, you should set the values for the sleepTime and mouseRgn parameters. These
  5598. parameters are used in the same way as the sleep and mouseRgn parameters of the
  5599. WaitNextEvent function. Specify in the sleepTime parameter the amount of time
  5600. (in ticks) during which your application agrees to relinquish the processor if
  5601. no events are pending for it.
  5602.  
  5603. In the mouseRgn parameter, you specify a screen region that determines the
  5604. conditions in which your application is to receive notice of mouse-moved events.
  5605. Your idle function receives mouse-moved events only if your application is the
  5606. front application and the mouse strays outside the region you specify.
  5607.  
  5608. Your idle function receives only update events, null events, operating-system
  5609. events, and activate events. When your idle function receives a null event, it
  5610. can use the idle time to update status reports, animate cursors, or perform
  5611. similar tasks. If your idle function receives any of the other events, it should
  5612. handle the event as it normally would if received in its event loop.
  5613.  
  5614. Listing 6-18 shows an example of an idle function that can be used as an idle
  5615. function for AESend or AEInteractWithUser. The idle function processes update
  5616. events, null events, operating-system events, and activate events. The first
  5617. time the function is called it receives a null event. At this time, it sets the
  5618. sleepTime and mouseRgn parameters. The function continues to process events
  5619. until the server finishes handling the Apple event or the user brings the
  5620. application to the front.
  5621.  
  5622. Your application should implement a method of checking to see if the user wants
  5623. to cancel. The MyCancelInQueue function in Listing 6-18 checks the event queue
  5624. for any instances of Command-period and immediately returns TRUE as its function
  5625. result if it finds a request to cancel in the event queue.
  5626.  
  5627. ¿ Listing 6-18   An idle function
  5628.  
  5629. FUNCTION MyIdleFunction (VAR event: EventRecord;
  5630.                          VAR sleeptime: LongInt;
  5631.                          VAR mouseRgn: RgnHandle) : Boolean;
  5632. VAR
  5633.    hiByte: CHAR;
  5634.    myErr:  OSErr;
  5635. BEGIN
  5636.    MyIdleFunction := FALSE;
  5637. {the MyCancelInQueue function checks the event queue for Command-period}
  5638.    IF MyCancelInQueue THEN
  5639.       BEGIN              
  5640.          MyIdleFunction := TRUE;
  5641.          Exit(MyIdleFunction );
  5642.       END;
  5643.    CASE event.what OF
  5644.       updateEvt,
  5645.       activateEvt,  {every idle function should handle these kinds }
  5646.       kOSEvent:    { of events}
  5647.          BEGIN
  5648.             AdjustCursor(event.where, gCursorRgn);  
  5649.             DoEvent(event);
  5650.          END;
  5651.       nullEvent:
  5652.          BEGIN
  5653.             {Set the sleepTime and mouseRgn parameters}
  5654.             mouseRgn := gCursorRgn;
  5655.             sleeptime := 10;  {use the correct value for your app}
  5656.             DoIdle;        {the application’s idle handling}
  5657.          END 
  5658.       END; {CASE}
  5659. END;
  5660. _______________________________________________________________________________
  5661.  
  5662. æKY Writing…a…Reply…Filter…Function
  5663. æC »Writing a Reply Filter Function                                The Apple Event Manager
  5664. _______________________________________________________________________________
  5665.  
  5666. If your application calls AESend and chooses to yield the processor to other
  5667. processes while waiting for a reply, you can provide an idle function to process
  5668. update, null, operating-system, and activate events and, additionally, you can
  5669. provide a reply filter function to process high-level events. The previous
  5670. section describes how an idle function processes events.
  5671.  
  5672. Your reply filter function can process any high-level events that it is willing
  5673. to handle while waiting for a reply Apple event. For example, your application
  5674. can choose to handle Apple events from other processes while waiting. Note,
  5675. however, that your application must maintain any necessary state information.
  5676. Your reply filter function must not accept any Apple events that can change the
  5677. state of your application and make it impossible to return to its previous
  5678. state.
  5679.  
  5680. A reply filter function must use this syntax:
  5681.  
  5682. FUNCTION MyWaitReplyFilter (VAR theEventRecord: EventRecord;
  5683.                             transactionID: LongInt; returnID: LongInt;
  5684.                             sender: AEAddressDesc) : Boolean;
  5685.  
  5686. The parameter theEventRecord is the event record for a high-level event. The
  5687. next three parameters contain valid information only if the event is an Apple
  5688. event. The transactionID parameter is the transaction ID for the Apple event.
  5689. The returnID parameter is the return ID for the Apple event. The sender
  5690. parameter contains the address of the application or process that sent the Apple
  5691. event.
  5692.  
  5693. Your reply filter function should return TRUE as the function result if you want
  5694. to accept the Apple event; otherwise it should return FALSE. If your filter
  5695. function returns TRUE, the Apple Event Manager calls the AEProcessAppleEvent
  5696. function on behalf of your application, and your handler routine is called to
  5697. process the Apple event.
  5698. _______________________________________________________________________________
  5699.  
  5700. æKY Writing…and…Installing…Coercion…Handlers
  5701. æC »Writing and Installing Coercion Handlers                       The Apple Event Manager
  5702. _______________________________________________________________________________
  5703.  
  5704. When your application extracts data from a parameter, it can request that the
  5705. Apple Event Manager return the data using a descriptor type that is different
  5706. from the original descriptor type. For example, when extracting data from the
  5707. direct parameter of the Open Documents event, you can request that the alias
  5708. records be returned as file system specification records. The Apple Event
  5709. Manager can automatically coerce many different types of data from one to
  5710. another. Table 6-1 later in this section shows descriptor types and the sorts of
  5711. coercion that the Apple Event Manager can perform.
  5712.  
  5713. You can also provide your own routines, referred to as coercion handlers, to
  5714. coerce other descriptor types. To install your own coercion handlers, use the
  5715. AEInstallCoercionHandler function. You specify as parameters to this function
  5716.  
  5717.   • the descriptor type of the data coerced by the handler
  5718.  
  5719.   • the descriptor type of the resulting data
  5720.  
  5721.   • the address of the coercion handler for this descriptor type
  5722.  
  5723.   • a reference constant
  5724.  
  5725.   • a Boolean value that indicates whether your coercion handler expects the
  5726.   data to
  5727.      be specified as a descriptor record or as a pointer to the actual data
  5728.  
  5729.   • a Boolean value that indicates whether your coercion handler should be added
  5730.  
  5731.      to your application’s coercion table or the system coercion table
  5732.  
  5733. The system coercion table is a table in the system heap that contains handlers
  5734. that are available to all applications and processes running on the same
  5735. computer. The handlers in your application’s coercion table are available only
  5736. to your application. When the Apple Event Manager is attempting to coerce data,
  5737. it first looks for a coercion handler in your application’s coercion table. If
  5738. it cannot find a handler for the descriptor type, it looks in the system
  5739. coercion table for a handler. If it doesn’t find a handler there either, it
  5740. returns the errAEHandlerNotFound result code.
  5741.  
  5742.    Note: When an application calls a system coercion handler, the A5 register is
  5743.    set 
  5744.    up for the calling application. For this reason, if you provide a system
  5745.    coercion 
  5746.    handler, it should never use A5 global variables or anything that depends on
  5747.    a 
  5748.    particular context; otherwise, the application that calls the system coercion
  5749.  
  5750.    handler may crash.
  5751.  
  5752. You can provide a coercion handler that expects to receive the data in a
  5753. descriptor record or a buffer referred to by a pointer. When you install your
  5754. coercion handler, you specify how your handler wishes to receive the data. It’s
  5755. more efficient for the Apple Event Manager to provide your coercion handler with
  5756. a pointer to the data so, whenever possible, you should write your coercion
  5757. handler so that it can accept a pointer to the data.
  5758.  
  5759. A coercion handler that accepts a pointer to data must be a function with the
  5760. following syntax:
  5761.  
  5762. FUNCTION MyCoercePtr (typeCode: DescType; dataPtr: Ptr;
  5763.                       dataSize: Size; toType: DescType;
  5764.                       handlerRefcon: LongInt;
  5765.                       VAR result: AEDesc) : OSErr; 
  5766.  
  5767. The typeCode parameter is the descriptor type of the original data. The dataPtr
  5768. parameter is a pointer to the data to coerce; the dataSize parameter is the
  5769. length, in bytes, of the data. The toType parameter is the desired descriptor
  5770. type of the resulting data. The handlerRefcon parameter is a reference constant
  5771. that is stored in the coercion table entry for the handler and passed to the
  5772. handler by the Apple Event Manager whenever the handler is called. The result
  5773. parameter is the resulting descriptor record returned by your coercion handler.
  5774.  
  5775. Your coercion handler should coerce the data to the desired descriptor type and
  5776. return the resulting data in the descriptor record specified by the result
  5777. parameter. Your handler should return the noErr result code if your handler
  5778. successfully performs the coercion, and a nonzero result code otherwise.
  5779.  
  5780. A coercion handler that accepts a descriptor record must be a function with the
  5781. following syntax:
  5782.  
  5783. FUNCTION MyCoerceDesc (theAEDesc: AEDesc; toType: DescType;
  5784.                        handlerRefcon: LongInt;
  5785.                        VAR result: AEDesc) : OSErr;
  5786.  
  5787. The parameter theAEDesc is the descriptor record that contains the data to be
  5788. coerced. The toType parameter is the descriptor type of the resulting data. The
  5789. handlerRefcon parameter is a reference constant that is stored in the coercion
  5790. table entry for the handler and passed to the handler by the Apple Event Manager
  5791. whenever the handler is called. The result parameter is the resulting descriptor
  5792. record.
  5793.  
  5794. Your coercion handler should coerce the data in the descriptor record to the
  5795. desired descriptor type and return the resulting data in the descriptor record
  5796. specified by the result parameter. Your handler should return an appropriate
  5797. result code.
  5798.  
  5799. Table 6-1 lists the descriptor types that the Apple Event Manager provides
  5800. coercion for. The first column shows the descriptor type of the data to be
  5801. coerced, and the second column shows the descriptor types that the Apple Event
  5802. Manager can coerce it to.
  5803.  
  5804.    Note: For many Apple Event Manager functions, the Apple Event Manager 
  5805.    attempts to coerce data to the descriptor type you specify even if the result
  5806.    is no 
  5807.    longer meaningful. To ensure that no coercion is performed and that the 
  5808.    descriptor type of the result is of the same descriptor type as the original,
  5809.    specify 
  5810.    typeWildCard for the desired type.
  5811.  
  5812. ¿ Table 6-1   Coercion handling provided by the Apple Event Manager
  5813. _________________________________________________________
  5814. Original                              Desired
  5815. Description
  5816. Descriptor type                  descriptor type
  5817.  
  5818. typeChar                             typeInteger                   Any string
  5819. that is a valid
  5820.                                               typeLongInteger
  5821.                                               representation of a number
  5822.                                               typeSMInt                    can
  5823.                                               be coerced into an
  5824.                                               typeSMFloat
  5825.                                               equivalent numeric value.
  5826.                                              typeShortInteger  
  5827.                                              typeLongFloat     
  5828.                                              typeShortFloat    
  5829.                                              typeExtended 
  5830.                                              typeComp
  5831.                                              typeMagnitude
  5832.  
  5833. typeInteger                         typeChar                       Any numeric
  5834. descriptor type
  5835. typeLongInteger                                                       can be
  5836. coerced into 
  5837. typeSMInt                                                                  the
  5838. equivalent text string.
  5839. typeSMFloat                                             
  5840. typeShortInteger                                        
  5841. typeLongFloat 
  5842. typeShortFloat 
  5843. typeExtended 
  5844. typeComp  
  5845. typeMagnitude
  5846.  
  5847. typeInteger                          typeInteger                 Any numeric
  5848. descriptor type
  5849. typeLongInteger                 typeLongInteger        can be coerced into any
  5850. other
  5851. typeSMInt                            typeSMInt                  numeric
  5852. descriptor type.
  5853.  
  5854. typeSMFloat                        typeSMFloat        
  5855. typeShortInteger                typeShortInteger                    
  5856. typeLongFloat                     typeLongFloat
  5857. typeShortFloat                    typeShortFloat
  5858. typeExtended                       typeExtended
  5859. typeComp                             typeComp 
  5860. typeMagnitude                    typeMagnitude
  5861.  
  5862. typeTrue                               typeBoolean            The result is the
  5863. Boolean value 
  5864.                                                                                
  5865.  
  5866.  
  5867. typeFalse                              typeBoolean             The result is the
  5868. Boolean value 
  5869.                                                                                
  5870.  
  5871.  
  5872. typeEnumerated                typeBoolean              The enumerated value
  5873. 'true' 
  5874.                                                                                
  5875.                                                                                
  5876.                                                                                
  5877.                                                                                
  5878.  
  5879.                                                                                
  5880.                                                                                
  5881.                                                                                
  5882.                                                                                
  5883.  
  5884.                                                                                
  5885.                                                                                
  5886.                                                                                
  5887.                                                                                
  5888.  
  5889.                                                                                
  5890.                                                                                
  5891.  
  5892.  
  5893. typeBoolean                        typeEnumerated      The Boolean value FALSE 
  5894.                                                                                
  5895.                                                                                
  5896.                                                                                
  5897.                                                                                
  5898.  
  5899.                                                                                
  5900.                                                                                
  5901.                                                                                
  5902.                                                                                
  5903.  
  5904.                                                                                
  5905.                                                                                
  5906.                                                                                
  5907.                                                                                
  5908.  
  5909.                                                                                
  5910.                                                                                
  5911.  
  5912.  
  5913. typeShortInteger                typeBoolean               A value of 1 becomes 
  5914.                                                                                
  5915.                                                                                
  5916.                                                                                
  5917.                                                                                
  5918.                                                                                
  5919.  
  5920.                                                                                
  5921.                                                                                
  5922.                                                                                
  5923.                                                                                
  5924.                                                                                
  5925.  
  5926.                                                                                
  5927.                                                                                
  5928.                                                                                
  5929.  
  5930.  
  5931. typeBoolean                       typeShortInteger       A value of FALSE
  5932. becomes 0.
  5933.                                                                                
  5934.                                                                                
  5935.                                                                                
  5936.                                                                                
  5937.                                                                                
  5938.                                                                                
  5939.  
  5940.  
  5941. typeAlias                             typeFSS                       An alias
  5942. record is coerced into a 
  5943.                                                                                
  5944.                                                                                
  5945.                                                                                
  5946.                                                                                
  5947.  
  5948.  
  5949. typeTemporaryID              typeSectionH            A temporary ID is coerced
  5950. into
  5951.                                                                                
  5952.                                                                                
  5953.                                                                                
  5954.                                                                                
  5955.                                                                                
  5956.                                                                                
  5957.  
  5958.  
  5959. typeAppleEvent                typeAppParameters  An Apple event is coerced 
  5960.                                                                                
  5961.                                                                                
  5962.                                                                                
  5963.                                                                                
  5964.                                                                                
  5965.  
  5966.                                                                                
  5967.                                                                                
  5968.                                                                                
  5969.  
  5970.                                                                                
  5971.  
  5972.                                                                                
  5973.                                                                                
  5974.  
  5975.  
  5976. any descriptor type            typeAEList                 A descriptor record is
  5977. coerced 
  5978.                                                                                
  5979.                                                                                
  5980.                                                                                
  5981.                                                                                
  5982.                                                                                
  5983.                                                                                
  5984.  
  5985.                                                                                
  5986.                                                                                
  5987.  
  5988.  
  5989. typeAEList                           type of list item         A descriptor list
  5990. containing a 
  5991.                                                                                
  5992.                                                                                
  5993.                                                                                
  5994.                                                                                
  5995.  
  5996.                                                                                
  5997.                                                                                
  5998.                                                                                
  5999.                                                                                
  6000.                                                                                
  6001.  
  6002. _______________________________________________________________________________
  6003.  
  6004. æKY The…Application…Died…Event
  6005. æC »The Application Died Event                                     The Apple Event Manager
  6006. _______________________________________________________________________________
  6007.  
  6008. If an application launched by your application terminates, either normally or as
  6009. the result of an error, the Process Manager can notify your application by
  6010. sending it an Apple event—the Application Died event. To receive this
  6011. notification, you must set the acceptAppDied flag in your application’s 'SIZE'
  6012. resource. (For a complete description of the 'SIZE' resource, see the Event
  6013. Manager chapter in this volume.) See the Process Management chapter in this
  6014. volume for information on how your application can launch other applications.
  6015.  
  6016. Application Died—inform that an application has terminated
  6017.  
  6018. Event class                        kCoreEventClass
  6019.  
  6020. Event ID                            kAEApplicationDied
  6021.  
  6022. Required parameters      Keyword:                 keyErrorNumber
  6023.                                              Descriptor type:
  6024.                                              typeLongInteger
  6025.                                              Data:                          A
  6026.                                              sign-extended OSErr value. A value
  6027.                                                                                
  6028.                                                                                
  6029.                                                                                
  6030.                                                                                
  6031.                                                                                
  6032.  
  6033.                                                                                
  6034.                                                                                
  6035.                                                                                
  6036.                                                                                
  6037.                                                                                
  6038.                                                                                
  6039.  
  6040.                                                                                
  6041.                                                                                
  6042.                                                                                
  6043.                                                                                
  6044.                                                                                
  6045.                                                                                
  6046.  
  6047.                                               Keyword:
  6048.                                               keyProcessSerialNumber
  6049.                                               Descriptor type:
  6050.                                               typeProcessSerialNumber
  6051.                                               Data:                        The
  6052.                                               process serial number of the  
  6053.                                                                                
  6054.                                                                                
  6055.                                                                                
  6056.  
  6057.  
  6058. Requested action              None. This Apple event is sent only to provide 
  6059.                                               information.
  6060.  
  6061. The Process Manager gets the value of the keyErrorNumber parameter from the
  6062. system global variable DSErrCode. This value can be set either by the
  6063. application before it terminates or by the Operating System (which can occur as
  6064. the result of a hardware exception or other problem).
  6065. _______________________________________________________________________________
  6066.  
  6067. æKY Apple…Event…Manager…Routines…Volume…VI
  6068. æC »Apple Event Manager Routines Volume VI                         The Apple Event Manager
  6069. _______________________________________________________________________________
  6070.  
  6071. This section describes the routines you use to manage Apple event dispatch
  6072. tables, process Apple events, get parameters and attributes from Apple events,
  6073. get data from Apple event data structures, create Apple event data structures,
  6074. add parameters and attributes to Apple events, send Apple events, get
  6075. information about and delete descriptor records, and coerce descriptor types.
  6076. Result codes appear at the end of each function as applicable.
  6077.  
  6078. _______________________________________________________________________________
  6079.  
  6080. æKY Creating…and…Managing…the…Apple…Event…Dispatch…Tables
  6081. æC »Creating and Managing the Apple Event Dispatch Tables          The Apple Event Manager
  6082. _______________________________________________________________________________
  6083.  
  6084. An Apple event dispatch table contains entries that specify the event class and
  6085. event ID that refer to one or more Apple events, the address of the handler
  6086. routine that handles those Apple events, and a reference constant. You use the
  6087. AEInstallEventHandler function to add entries to the Apple event dispatch table.
  6088. Using this function sets up the initial mapping between the handlers in your
  6089. application and the Apple events that they handle.
  6090.  
  6091. If you need to remove any of your Apple event handlers after this mapping is
  6092. established, you can use the AERemoveEventHandler function. To get the address
  6093. of a handler currently in the Apple event dispatch table, use the
  6094. AEGetEventHandler function.
  6095.  
  6096. You use the AEInstallEventHandler function to add an entry to either the
  6097. application or system Apple event dispatch table.
  6098.  
  6099. To create an entry in the Apple event dispatch table, supply the event class,
  6100. event ID, and address of the handler routine that handles Apple events of the
  6101. specified event class and event ID. You also specify a reference constant that
  6102. the Apple Event Manager passes to your handler routine whenever your handler
  6103. processes an Apple event.
  6104.  
  6105. FUNCTION AEInstallEventHandler (theAEEventClass: AEEventClass; 
  6106.                                 theAEEventID: AEEventID; handler: 
  6107.                                 EventHandlerProcPtr; handlerRefcon: 
  6108.                                 LongInt; isSysHandler: Boolean) : OSErr;
  6109.  
  6110. The parameters theAEEventClass and theAEEventID specify the event class and
  6111. event ID of the Apple events to be handled by the handler for this dispatch
  6112. table entry. For these parameters, you must provide one of the following
  6113. combinations:
  6114.  
  6115.   • the event class and event ID of a single Apple event to be dispatched to the
  6116.  
  6117.      handler for this dispatch table entry
  6118.  
  6119.   • the typeWildCard constant for theAEEventClass and an event ID for 
  6120.      theAEEventID, which indicates that Apple events from all event classes
  6121.      whose 
  6122.      event IDs match theAEEventID should be dispatched to the handler for this 
  6123.      dispatch table entry
  6124.  
  6125.   • an event class for theAEEventClass and the typeWildCard constant for 
  6126.      theAEEventID, which indicates that all events from the event class 
  6127.      theAEEventClass should be dispatched to the handler for this dispatch table
  6128.  
  6129.      entry
  6130.  
  6131.   • the typeWildCard constant for both the parameters theAEEventClass and 
  6132.      theAEEventID, which specifies that all Apple events should be dispatched to
  6133.      the 
  6134.      handler for this dispatch table entry
  6135.  
  6136. The handler parameter is a pointer to an Apple event handler for this dispatch
  6137. table entry. Note that a handler in the system dispatch table must reside in the
  6138. system heap; this means that if the value of the isSysHandler parameter is TRUE,
  6139. the handler parameter must point to a location in the system heap.
  6140.  
  6141. The handlerRefcon parameter is a reference constant that is passed by the Apple
  6142. Event Manager to the handler each time the handler is called. If your handler
  6143. doesn’t use a reference constant, use 0 as the value of this parameter. 
  6144.  
  6145. The isSysHandler parameter specifies the Apple event dispatch table to which you
  6146. want to add the handler. If the value of isSysHandler is TRUE, the Apple Event
  6147. Manager adds the handler to the system Apple event dispatch table. Entries in
  6148. the system Apple event dispatch table are available to all applications. If the
  6149. value of isSysHandler is FALSE, the Apple Event Manager adds the handler to your
  6150. application’s Apple event dispatch table. The application Apple event dispatch
  6151. table is searched first; the system Apple event dispatch table is searched only
  6152. if the necessary handler is not found in your application’s Apple event dispatch
  6153. table.
  6154.  
  6155. If there was already an entry in the specified event handler table for the same
  6156. event class and event ID, it is replaced. Therefore, before installing a handler
  6157. for a particular Apple event into the system dispatch table, use the
  6158. AEGetEventHandler function to determine if the table already contains a handler
  6159. for that event. If an entry exists, AEGetEventHandler returns a reference
  6160. constant and a pointer to that event handler. Chain these to your event handler
  6161. by providing pointers to the previous handler and its reference constant in the
  6162. handlerRefcon parameter of AEInstallEventHandler. When your handler is finished,
  6163. use these pointers to call the previous handler.
  6164.  
  6165. If you put your handler code in the system heap or in your own heap, use the
  6166. AERemoveHandler function to remove the handler when your application quits.
  6167.  
  6168.    Note: When an application calls a system Apple event handler, the A5 register
  6169.    is 
  6170.    set up for the calling application. For this reason, if you provide a system
  6171.    Apple 
  6172.    event handler, it should never use A5 global variables or anything that
  6173.    depends 
  6174.    on a particular context; otherwise, the application that calls the system
  6175.    handler 
  6176.    may crash.
  6177.  
  6178.    Result codes
  6179.           noErr                       0         No error
  6180.           paramErr            –50         Parameter error (handler pointer is
  6181.           NIL or odd)
  6182.          memFullErr      –108        Not enough room in heap zone
  6183.  
  6184. The AEGetEventHandler function gets an entry from an Apple event dispatch table.
  6185.  
  6186. FUNCTION AEGetEventHandler (theAEEventClass: AEEventClass; theAEEventID: 
  6187.                             AEEventID; VAR handler: EventHandlerProcPtr; 
  6188.                             VAR handlerRefcon: LongInt; isSysHandler: 
  6189.                             Boolean) : OSErr;
  6190.  
  6191. The parameter theAEEventClass is the value of the event class field of the
  6192. dispatch table entry for the desired Apple event handler, and the parameter
  6193. theAEEventID is the value of the event ID field of the dispatch table entry for
  6194. the desired Apple event handler. You can use the typeWildCard constant for
  6195. either or both of these parameters. (For an explanation of wildcard values, see
  6196. the earlier description of the AEInstallEventHandler function.)
  6197.  
  6198. In the handler parameter, the AEGetEventHandler function returns a pointer to
  6199. the Apple event handler.
  6200.  
  6201. In the handlerRefcon parameter, the AEGetEventHandler function returns the
  6202. reference constant that is passed by the Apple Event Manager to the Apple event
  6203. handler each time the handler is called.
  6204.  
  6205. The isSysHandler parameter specifies the Apple event dispatch table from which
  6206. to get the handler. If isSysHandler is TRUE, the AEGetEventHandler function
  6207. returns the handler from the system dispatch table. If isSysHandler is FALSE,
  6208. AEGetEventHandler returns the handler from your application’s dispatch table.
  6209.  
  6210.    Result codes
  6211.           noErr                                                0        No error
  6212.           errAEHandlerNotFound    –1717        No handler found for an Apple
  6213.           event
  6214.  
  6215. The AERemoveEventHandler function removes an entry from an Apple event dispatch
  6216. table.
  6217.  
  6218. FUNCTION AERemoveEventHandler (theAEEventClass: AEEventClass; 
  6219.                                theAEEventID: AEEventID; handler: 
  6220.                                EventHandlerProcPtr; isSysHandler: 
  6221.                                Boolean) : OSErr;
  6222.  
  6223. The parameter theAEEventClass is the event class for the handler to be removed.
  6224. The parameter theAEEventID is the event ID for the handler to be removed. You
  6225. can use the typeWildCard constant for either or both of these parameters. (For
  6226. an explanation of wildcard values, see the earlier description of the
  6227. AEInstallEventHandler function.)
  6228.  
  6229. The handler parameter is a pointer to the Apple event handler to be removed.
  6230. Although the parameters theAEEventClass and theAEEventID would be sufficient to
  6231. identify the handler to be removed, providing the handler parameter is a
  6232. safeguard that ensures that you’re removing the correct handler.
  6233.  
  6234. The isSysHandler parameter specifies the Apple event dispatch table from which
  6235. to remove the handler. If TRUE, AERemoveEventHandler removes the handler from
  6236. the system dispatch table. If FALSE, AERemoveEventHandler removes the handler
  6237. from your application’s dispatch table.
  6238.  
  6239.    Result codes
  6240.           noErr                                                 0       No error
  6241.           errAEHandlerNotFound     –1717       No handler found for an Apple
  6242.           event
  6243. _______________________________________________________________________________
  6244.  
  6245. æKY Dispatching…Apple…Events
  6246. æC »Dispatching Apple Events                                       The Apple Event Manager
  6247. _______________________________________________________________________________
  6248.  
  6249. After receiving a high-level event (and optionally checking whether it is a type
  6250. of high-level event other than an Apple event that your application might
  6251. support), your application typically calls the AEProcessAppleEvent function to
  6252. determine the type of Apple event received and to call the corresponding handler
  6253. routine.
  6254.  
  6255. The AEProcessAppleEvent function looks first in the application Apple event
  6256. dispatch table and then in the system Apple event dispatch table for an entry
  6257. that matches the event class and event ID of the specified Apple event. If
  6258. AEProcessAppleEvent finds a matching entry, it calls the handler for that Apple
  6259. event.
  6260.  
  6261. FUNCTION AEProcessAppleEvent (theEventRecord: EventRecord) : OSErr;
  6262.  
  6263. The parameter theEventRecord is the event record for the Apple event.
  6264.  
  6265. If the AEProcessAppleEvent function cannot find a handler for an Apple event in
  6266. either the application or system Apple event dispatch table, the Apple Event
  6267. Manager returns the result code errAEEventNotHandled to the server application
  6268. (as the result of the AEProcessAppleEvent function). The Apple Event Manager
  6269. also returns this result code to the client application if the client is waiting
  6270. for a reply.
  6271.  
  6272.    Result codes
  6273.          noErr                                               0       No error
  6274.          memFullErr                            –108       Not enough room in
  6275.          heap zone
  6276.           bufferIsSmall                          –607       Buffer is too small
  6277.           noOutstandingHLE               –608       No outstanding high-level
  6278.           event
  6279.           errAECorruptData               –1702       Data in an Apple event
  6280.           could not be read
  6281.           errAENewerVersion           –1706      Need a newer version of the
  6282.           Apple Event 
  6283.  
  6284.  
  6285.           errAENotAppleEvent         –1707      Event is not an Apple event
  6286.           errAEHandlerNotFound    –1708     A handler for the Apple event wasn’t
  6287.  
  6288.                                                                            found
  6289. _______________________________________________________________________________
  6290.  
  6291. æKY Getting…Parameters…and…Attributes…From…Apple…Events
  6292. æC »Getting Parameters and Attributes From Apple Events            The Apple Event Manager
  6293. _______________________________________________________________________________
  6294.  
  6295. You use the AEGetParamPtr and AEGetParamDesc functions to gain access to the
  6296. parameters of an Apple event. You use the AEGetAttributePtr and
  6297. AEGetAttributeDesc functions to gain access to the attributes of an Apple event.
  6298.  
  6299. The AEGetParamPtr function uses a buffer to return the data contained in a
  6300. specified parameter of an Apple event.
  6301.  
  6302. FUNCTION AEGetParamPtr (theAppleEvent: AppleEvent; theAEKeyword: 
  6303.                         AEKeyword; desiredType: DescType; VAR typeCode: 
  6304.                         DescType; dataPtr: Ptr; maximumSize: Size; 
  6305.                         VAR actualSize: Size) : OSErr;
  6306.  
  6307. The parameter theAppleEvent is the Apple event containing the desired parameter.
  6308.  
  6309. The parameter theAEKeyword is the keyword that specifies the desired parameter.
  6310.  
  6311. The desiredType parameter specifies the descriptor type of the resulting data;
  6312. if the desired parameter is not of this type, the Apple Event Manager attempts
  6313. to coerce it into this type. If the value of desiredType is typeWildCard, no
  6314. coercion is performed, and the descriptor type of the returned data is the same
  6315. as the descriptor type of the parameter. The returned data’s descriptor type is
  6316. returned in the typeCode parameter.
  6317.  
  6318. The dataPtr parameter is a pointer to the buffer for storing the returned data.
  6319.  
  6320. The maximumSize parameter is the maximum length, in bytes, of the data to be
  6321. returned. You must allocate at least this amount of storage for the buffer
  6322. specified by the dataPtr parameter. 
  6323.  
  6324. The AEGetParamPtr function returns in the actualSize parameter the actual
  6325. length, in bytes, of the data for the Apple event parameter. If this value is
  6326. larger than the value of maximumSize, not all of the data for the Apple event
  6327. parameter was returned.
  6328.  
  6329.    Result codes
  6330.           noErr                                             0         No error
  6331.           memFullErr                          –108         Not enough room in
  6332.           heap zone
  6333.           errAECoercionFail             –1700         Data could not be coerced
  6334.           to the requested
  6335.  
  6336.  
  6337.  
  6338.           errAEDescNotFound         –1701         Descriptor record was not
  6339.           found
  6340.           errAEWrongDataType      –1703         Wrong descriptor type
  6341.           errAENotAEDesc                –1704         Not a valid descriptor
  6342.           record
  6343.           errAEReplyNotArrived    –1718         Reply has not yet arrived
  6344.  
  6345. The AEGetParamDesc function returns the descriptor record for an Apple event
  6346. parameter. 
  6347.  
  6348. FUNCTION AEGetParamDesc (theAppleEvent: AppleEvent; theAEKeyword: 
  6349.                          AEKeyword; desiredType: DescType; 
  6350.                          VAR result: AEDesc) : OSErr;
  6351.  
  6352. The parameter theAppleEvent is the Apple event containing the desired parameter.
  6353.  
  6354. The parameter theAEKeyword is the keyword that specifies the desired parameter.
  6355.  
  6356. The desiredType parameter specifies the descriptor type of the resulting
  6357. descriptor record; if the parameter is not of this type, the Apple Event Manager
  6358. attempts to coerce it into this type. If the value of desiredType is
  6359. typeWildCard, no coercion is performed, and the descriptor type of the resulting
  6360. descriptor record is the same as the descriptor type of the Apple event’s
  6361. parameter.
  6362.  
  6363. The AEGetParamDesc function returns in the result parameter the resulting
  6364. descriptor record. This function creates a new descriptor record by copying the
  6365. descriptor record from the parameter. Your application is responsible for using
  6366. the AEDisposeDesc function to dispose of the resulting descriptor record once
  6367. you are finished using it.
  6368.  
  6369. If the function returns a nonzero result code, a descriptor record with the
  6370. typeNull descriptor type is returned. A descriptor record of this type does not
  6371. contain any data.
  6372.  
  6373.    Result codes
  6374.          noErr                                           0       No error
  6375.          memFullErr                        –108       Not enough room in heap
  6376.          zone
  6377.          errAECoercionFail           –1700       Data could not be coerced to
  6378.          the requested 
  6379.  
  6380.                                                                         type
  6381.          errAEDescNotFound        –1701      Descriptor type was not found
  6382.          errAENotAEDesc               –1704      Not a valid descriptor record
  6383.          errAEReplyNotArrived   –1718      Reply has not yet arrived
  6384.  
  6385. The AEGetAttributePtr function uses a buffer to return the data contained in an
  6386. Apple event attribute.
  6387.  
  6388. FUNCTION AEGetAttributePtr (theAppleEvent: AppleEvent; theAEKeyword: 
  6389.                             AEKeyword; desiredType: DescType; 
  6390.                             VAR typeCode: DescType; dataPtr: Ptr; 
  6391.                             maximumSize: Size; VAR actualSize: 
  6392.                             Size) : OSErr;
  6393.  
  6394. The parameter theAppleEvent is the Apple event containing the desired attribute.
  6395.  
  6396. The parameter theAEKeyword is the keyword that specifies the desired attribute.
  6397.  
  6398. The desiredType parameter is the descriptor type of the data to be returned; if
  6399. the desired attribute is not of this type, the Apple Event Manager attempts to
  6400. coerce it into this type. If the value of desiredType is typeWildCard, no
  6401. coercion is performed, and the descriptor type of the returned data is the same
  6402. as the descriptor type of the attribute. The returned data’s descriptor type is
  6403. returned in the typeCode parameter.
  6404.  
  6405. The dataPtr parameter is a pointer to the buffer for storing the data that is
  6406. returned.
  6407.  
  6408. The maximumSize parameter is the maximum length, in bytes, of the data to be
  6409. returned.
  6410.  
  6411. The AEGetAttributePtr function returns in the actualSize parameter the actual
  6412. length, in bytes, of the data for the attribute. If this value is larger than
  6413. the value of maximumSize, not all of the data for the attribute was returned.
  6414.  
  6415.    Result codes
  6416.          noErr                                          0          No error
  6417.          memFullErr                        –108         Not enough room in heap
  6418.          zone
  6419.          errAECoercionFail           –1700         Data could not be coerced to
  6420.          the requested 
  6421.  
  6422.                                                                           type
  6423.          errAEDescNotFound        –1701        Descriptor type was not found
  6424.          errAENotAEDesc              –1704        Not a valid descriptor record
  6425.          errAEReplyNotArrived   –1718       Reply has not yet arrived
  6426.  
  6427. The AEGetAttributeDesc function returns the descriptor record for an Apple event
  6428. attribute.
  6429.  
  6430. FUNCTION AEGetAttributeDesc (theAppleEvent: AppleEvent; theAEKeyword: 
  6431.                              AEKeyword; desiredType: DescType; 
  6432.                              VAR result: AEDesc) : OSErr;
  6433.  
  6434. The parameter theAppleEvent is the Apple event containing the desired attribute.
  6435.  
  6436. The parameter theAEKeyword is the keyword that specifies the desired attribute.
  6437.  
  6438. The desiredType parameter is the descriptor type of the descriptor record to be
  6439. returned; if the desired attribute is not of this type, the Apple Event Manager
  6440. attempts to coerce it into this type. If the value of desiredType is
  6441. typeWildCard, no coercion is performed, and the descriptor type of the resulting
  6442. descriptor record is the same as the descriptor type of the attribute.
  6443.  
  6444. The AEGetAttributeDesc function returns in the result parameter the resulting
  6445. descriptor record. This function creates a new descriptor record by copying the
  6446. descriptor record from the parameter. Your application is responsible for using
  6447. the AEDisposeDesc function to dispose of the resulting descriptor record once
  6448. you are finished using it.
  6449.  
  6450. If the function returns a nonzero result code, a descriptor record with the
  6451. typeNull descriptor type is returned. A descriptor record of this type does not
  6452. contain any data.
  6453.  
  6454.    Result codes
  6455.          noErr                                                0       No error
  6456.          memFullErr                             –108       Not enough room in
  6457.          heap zone
  6458.          errAECoercionFail                –1700       Data could not be coerced
  6459.          to the requested
  6460.  
  6461.  
  6462.  
  6463.          errAEDescNotFound            –1701       Descriptor record was not
  6464.          found
  6465.          errAENotAEDesc                  –1704        Not a valid descriptor
  6466.          record
  6467.          errAEReplyNotArrived       –1718        Reply has not yet arrived
  6468. _______________________________________________________________________________
  6469.  
  6470. æKY Counting…the…Items…in…Descriptor…Lists
  6471. æC »Counting the Items in Descriptor Lists                         The Apple Event Manager
  6472. _______________________________________________________________________________
  6473.  
  6474. The AECountItems function counts the number of descriptor records in a
  6475. descriptor list.
  6476.  
  6477. FUNCTION AECountItems (theAEDescList: AEDescList; VAR theCount:
  6478.                        LongInt) : OSErr;
  6479.  
  6480. The parameter theAEDescList is the descriptor list to be counted.
  6481.  
  6482. The AECountItems function returns the number of descriptor records in the list
  6483. in the parameter theCount.
  6484.  
  6485.    Result codes
  6486.           noErr                                   0         No error
  6487.           errAENotAEDesc     –1704         Not a valid descriptor record
  6488. _______________________________________________________________________________
  6489.  
  6490. æKY Getting…Items…From…Descriptor…Lists
  6491. æC »Getting Items From Descriptor Lists                            The Apple Event Manager
  6492. _______________________________________________________________________________
  6493.  
  6494. You can use the AEGetNthPtr and AEGetNthDesc functions to gain access to the
  6495. data in a descriptor list. You can use the AEGetArray function to get data from
  6496. an array contained in a descriptor list.
  6497.  
  6498. The AEGetNthPtr function uses a buffer to return the data for a descriptor
  6499. record in a descriptor list.
  6500.  
  6501. FUNCTION AEGetNthPtr (theAEDescList: AEDescList; index: LongInt; 
  6502.                       desiredType: DescType; VAR theAEKeyword: 
  6503.                       AEKeyword; VAR typeCode: DescType; dataPtr: 
  6504.                       Ptr; maximumSize: Size; VAR actualSize: Size) : 
  6505.                       OSErr;
  6506.  
  6507. The parameter theAEDescList is the descriptor list containing the desired
  6508. descriptor record.
  6509.  
  6510. The index parameter specifies the position of the desired descriptor record in
  6511. the list (for example, 2 specifies the second descriptor record).
  6512.  
  6513. The desiredType parameter is the descriptor type of the resulting data; if the
  6514. descriptor record is not of this type, the Apple Event Manager attempts to
  6515. coerce it into this type. If the value of desiredType is typeWildCard, no
  6516. coercion is performed, and the descriptor type of the resulting data is the same
  6517. as the descriptor type of the original descriptor record.
  6518.  
  6519. If you are getting data from a list of keyword-specified descriptor records, the
  6520. keyword of the specified descriptor record is returned in the parameter
  6521. theAEKeyword; otherwise, the value typeWildCard is returned.
  6522.  
  6523. The returned data’s descriptor type is returned in the typeCode parameter.
  6524.  
  6525. The dataPtr parameter is the pointer to the buffer for storing the data.
  6526.  
  6527. The maximumSize parameter is the maximum length, in bytes, of the data to be
  6528. returned.
  6529.  
  6530. The AEGetNthPtr function returns in the actualSize parameter the actual length,
  6531. in bytes, of the data for the descriptor record. If this value is larger than
  6532. the value of maximumSize, not all of the data for the descriptor record was
  6533. returned.
  6534.  
  6535.    Result codes
  6536.           noErr                                               0       No error
  6537.           memFullErr                            –108       Not enough room in
  6538.           heap zone
  6539.           errAECoercionFail               –1700       Data could not be coerced
  6540.           to the requested
  6541.  
  6542.  
  6543.  
  6544.           errAEDescNotFound           –1701       Descriptor record was not
  6545.           found
  6546.           errAEWrongDataType        –1703        Wrong descriptor type
  6547.           errAENotAEDesc                 –1704        Not a valid descriptor
  6548.           record
  6549.           errAEReplyNotArrived      –1718        Reply has not yet arrived
  6550.  
  6551. The AEGetNthDesc function returns a descriptor record from a descriptor list.
  6552.  
  6553. FUNCTION AEGetNthDesc (theAEDescList: AEDescList; index: LongInt; 
  6554.                        desiredType: DescType; VAR theAEKeyword: 
  6555.                        AEKeyword; VAR result: AEDesc) : OSErr;
  6556.  
  6557. The parameter theAEDescList is the descriptor list from which to get the
  6558. descriptor record.
  6559.  
  6560. The index parameter is the position of the descriptor record to get (for
  6561. example, 2 specifies the second descriptor record in the list).
  6562.  
  6563. The desiredType parameter is the descriptor type of the resulting data; if the
  6564. descriptor record is not of this type, the Apple Event Manager attempts to
  6565. coerce it into this type. If the value of desiredType is typeWildCard, no
  6566. coercion is performed, and the descriptor type of the resulting descriptor
  6567. record is the same as the descriptor type of the original descriptor record.
  6568.  
  6569. If you are getting data from a list of keyword-specified descriptor records, the
  6570. AEGetNthDesc function returns the keyword of the specified descriptor record in
  6571. the parameter theAEKeyword; otherwise, AEGetNthDesc returns the typeWildCard
  6572. constant.
  6573.  
  6574. The AEGetNthDesc function returns in the result parameter the resulting
  6575. descriptor record. This function creates a new descriptor record by copying the
  6576. descriptor record from the parameter. Your application is responsible for using
  6577. the AEDisposeDesc function to dispose of the resulting descriptor record once
  6578. you are finished using it.
  6579.  
  6580. If the function returns a nonzero result code, a descriptor record with the
  6581. typeNull descriptor type is returned. A descriptor record of this type does not
  6582. contain any data.
  6583.  
  6584.    Result codes
  6585.          noErr                                             0     No error
  6586.          memFullErr                          –108     Not enough room in heap
  6587.          zone
  6588.          errAECoercionFail             –1700     Data could not be coerced to
  6589.          the requested 
  6590.  
  6591.                                                                         type
  6592.          errAEDescNotFound         –1701     Descriptor record was not found
  6593.          errAENotAEDesc                –1704     Not a valid descriptor record
  6594.          errAEReplyNotArrived    –1718     Reply has not yet arrived
  6595.  
  6596. The AEGetArray function converts an Apple event array (an array created with the
  6597. AEPutArray function and stored in a descriptor list) into the corresponding
  6598. Pascal or C array.
  6599.  
  6600. FUNCTION AEGetArray (theAEDescList: AEDescList; arrayType: AEArrayType; 
  6601.                      arrayPtr: AEArrayDataPointer; maximumSize: Size; 
  6602.                      VAR itemType: DescType; VAR itemSize: Size; 
  6603.                      VAR itemCount: LongInt) : OSErr;
  6604.  
  6605. The parameter theAEDescList is the descriptor list from which to get the array.
  6606.  
  6607. The arrayType parameter is the Apple event array type to be converted. This is
  6608. specified by one of the following constants: kAEDataArray, kAEPackedArray,
  6609. kAEHandleArray, kAEDescArray, or kAEKeyDescArray.
  6610.  
  6611. The arrayPtr parameter is a pointer to the buffer for storing the array.
  6612.  
  6613. The maximumSize parameter is the maximum length, in bytes, of the data to be
  6614. returned.
  6615.  
  6616. For packed, data, and handle arrays, the itemType parameter returns the
  6617. descriptor type of the array elements that are returned.
  6618.  
  6619. For packed and data arrays, the itemSize parameter returns the size, in bytes,
  6620. of the array elements that are returned.
  6621.  
  6622. The itemCount parameter returns the number of items in the resulting array.
  6623.  
  6624.    Result codes
  6625.           noErr                                              0     No error
  6626.           memFullErr                           –108     Not enough room in heap
  6627.           zone
  6628.           errAEWrongDataType       –1703     Wrong descriptor type
  6629.           errAENotAEDesc                –1704     Not a valid descriptor record
  6630.           errAEReplyNotArrived    –1718     Reply has not yet arrived
  6631. _______________________________________________________________________________
  6632.  
  6633. æKY Getting…Data…From…AE…Records
  6634. æC »Getting Data From AE Records                                   The Apple Event Manager
  6635. _______________________________________________________________________________
  6636.  
  6637. You can use the AEGetKeyPtr and AEGetKeyDesc functions to get data and
  6638. keyword-specified descriptor records out of an AE record or an Apple event.
  6639.  
  6640. The AEGetKeyPtr function uses a buffer to return the data contained in a
  6641. keyword-specified descriptor record. You can use this function to get data out
  6642. of an AE record or an Apple event record.
  6643.  
  6644. FUNCTION AEGetKeyPtr (theAERecord: AERecord; theAEKeyword: AEKeyword; 
  6645.                       desiredType: DescType; VAR typeCode: DescType; 
  6646.                       dataPtr: Ptr; maximumSize: Size; VAR actualSize: 
  6647.                       Size) : OSErr;
  6648.  
  6649. The parameter theAERecord is the AE record from which to get data.
  6650.  
  6651. The parameter theAEKeyword is the keyword that specifies the desired descriptor
  6652. record.
  6653.  
  6654. The desiredType parameter specifies the descriptor type of the resulting data;
  6655. if the desired data is not of this type, the Apple Event Manager attempts to
  6656. coerce it into this type. If the value of desiredType is typeWildCard, no
  6657. coercion is performed, and the descriptor type of resulting data is the same as
  6658. the descriptor type of the original data. The returned data’s descriptor type is
  6659. returned in the typeCode parameter.
  6660.  
  6661. The dataPtr parameter is a pointer to the buffer for storing the data.
  6662.  
  6663. The maximumSize parameter is the maximum length, in bytes, of the data to be
  6664. returned.
  6665.  
  6666. The AEGetKeyPtr function returns in the actualSize parameter the actual length,
  6667. in bytes, of the data for the keyword-specified descriptor record. If this value
  6668. is larger than the value of maximumSize, not all of the data for the
  6669. keyword-specified descriptor record was returned.
  6670.  
  6671.    Result codes
  6672.           noErr                                            0      No error
  6673.           memFullErr                         –108      Not enough room in heap
  6674.           zone
  6675.           errAECoercionFail            –1700      Data could not be coerced to
  6676.           the requested 
  6677.  
  6678.                                                                          type
  6679.           errAEDescNotFound         –1701     Descriptor record was not found
  6680.           errAEWrongDataType      –1703     Wrong descriptor type
  6681.           errAENotAEDesc                –1704     Not a valid descriptor record
  6682.           errAEReplyNotArrived    –1718     Reply has not yet arrived
  6683.  
  6684. The AEGetKeyDesc function returns the descriptor record for a keyword-specified
  6685. descriptor record. You can use this function to get a descriptor record out of
  6686. an AE record or an Apple event.
  6687.  
  6688. FUNCTION AEGetKeyDesc (theAERecord: AERecord; theAEKeyword: AEKeyword; 
  6689.                        desiredType: DescType; VAR result: AEDesc) : 
  6690.                        OSErr;
  6691.  
  6692. The parameter theAERecord is the AE record from which to get the descriptor
  6693. record.
  6694.  
  6695. The parameter theAEKeyword is the keyword that specifies the descriptor record
  6696. to be returned.
  6697.  
  6698. The desiredType parameter specifies the descriptor type of the resulting
  6699. descriptor record; if the original descriptor record is not of this type, the
  6700. Apple Event Manager attempts to coerce it into this type. If the value of
  6701. desiredType is typeWildCard, no coercion is performed, and the descriptor type
  6702. of the resulting descriptor record is the same as the descriptor type of the
  6703. original descriptor record.
  6704.  
  6705. The AEGetKeyDesc function returns in the result parameter the resulting
  6706. descriptor record. This function creates a new descriptor record by copying the
  6707. descriptor record from the AE record. Your application is responsible for using
  6708. the AEDisposeDesc function to dispose of the resulting descriptor record once
  6709. you are finished using it.
  6710.  
  6711. If the function returns a nonzero result code, a descriptor record with the
  6712. typeNull descriptor type is returned. A descriptor record of this type does not
  6713. contain any data.
  6714.  
  6715.    Result codes
  6716.           noErr                                              0     No error
  6717.           memFullErr                           –108     Not enough room in heap
  6718.           zone
  6719.           errAECoercionFail              –1700     Data could not be coerced to
  6720.           the requested 
  6721.  
  6722.                                                                           type
  6723.          errAEDescNotFound           –1701     Descriptor record was not found
  6724.          errAENotAEDesc                 –1704      Not a valid descriptor record
  6725.          errAEReplyNotArrived     –1718      Reply has not yet arrived
  6726. _______________________________________________________________________________
  6727.  
  6728. æKY Requesting…User…Interaction
  6729. æC »Requesting User Interaction                                    The Apple Event Manager
  6730. _______________________________________________________________________________
  6731.  
  6732. Your server application may need to interact with the user while processing an
  6733. Apple event. Your application should use the AEInteractWithUser function before
  6734. actually interacting with the user in response to an Apple event. Your
  6735. application can also specify its user interaction preferences by using the
  6736. AESetInteractionAllowed and AEGetInteractionAllowed functions.
  6737.  
  6738. A server application uses the AESetInteractionAllowed function to specify user
  6739. interaction preferences for responding to Apple events.
  6740.  
  6741. FUNCTION AESetInteractionAllowed (level: AEInteractAllowed) : OSErr;
  6742.  
  6743. The level parameter must be one of three flags: kAEInteractWithSelf,
  6744. kAEInteractWithLocal, or kAEInteractWithAll.
  6745.  
  6746. Specifying the kAEInteractWithSelf flag allows the server application to
  6747. interact with the user in response to an Apple event only when the client
  6748. application and server application are the same—that is, only when the
  6749. application is sending the Apple event to itself.
  6750.  
  6751. Specifying the kAEInteractWithLocal flag allows the server application to
  6752. interact with the user in response to an Apple event only if the client
  6753. application is on the same computer as the server application; this is the
  6754. default if the AESetInteractionAllowed function is not used.
  6755.  
  6756. Specifying the kAEInteractWithAll flag allows the server application to interact
  6757. with the user in response to an Apple event sent from any client application on
  6758. any computer.
  6759.  
  6760.    Result code
  6761.           noErr                                       0           No error
  6762.  
  6763. The AEGetInteractionAllowed function returns a value that indicates the user
  6764. interaction preferences for responding to an Apple event. The value returned is
  6765. the interaction level set by a previous call to AESetInteractionAllowed. The
  6766. default value of kAEInteractWithLocal is returned if your application has not
  6767. used AESetInteractionAllowed to explicitly set the interaction level.
  6768.  
  6769. FUNCTION AEGetInteractionAllowed (VAR level: AEInteractAllowed) : 
  6770.                                   OSErr;
  6771.  
  6772. The level parameter returns one of the following flags: kAEInteractWithSelf,
  6773. kAEInteractWithLocal, or kAEInteractWithAll.
  6774.  
  6775. The kAEInteractWithSelf flag indicates that the server application may interact
  6776. with the user in response to an Apple event only when the client application and
  6777. server application are the same—that is, only when the application is sending
  6778. the Apple event to itself.
  6779.  
  6780. The kAEInteractWithLocal flag indicates that the server application may interact
  6781. with the user in response to an Apple event only if the client application is on
  6782. the same computer as the server application. This is the default if your
  6783. application has not used the AESetInteractionAllowed function to explicitly set
  6784. the interaction level.
  6785.  
  6786. The kAEInteractWithAll flag indicates that the server application may interact
  6787. with the user in response to an Apple event sent from any client application on
  6788. any computer.
  6789.  
  6790.    Result code
  6791.           noErr                                       0           No error
  6792.  
  6793. A server application calls the AEInteractWithUser function before displaying a
  6794. dialog box or alert box or otherwise interacting with the user. If the
  6795. user-interaction preference settings permit the application to come to the
  6796. foreground, this function brings your application to the front, either directly
  6797. or by posting a notification request. 
  6798.  
  6799. FUNCTION AEInteractWithUser (timeOutInTicks: LongInt; nmReqPtr: 
  6800.                              QElemPtr; idleProc: IdleProcPtr) : OSErr;
  6801.  
  6802. The timeOutInTicks parameter is the amount of time (in ticks) that your handler
  6803. is willing to wait for a response from the user.
  6804.  
  6805. The nmReqPtr parameter is a pointer to a Notification Manager record provided by
  6806. your application. You can specify NIL for this parameter to get the default
  6807. notification handling provided by the Apple Event Manager.
  6808.  
  6809. The idleProc parameter is a pointer to your application’s idle function, which
  6810. handles events while waiting for the Apple Event Manager to return control. For
  6811. a description of how to write this function, see “Writing an Idle Function”
  6812. earlier in this chapter.
  6813.  
  6814. The AEInteractWithUser function checks to see if the client application set the
  6815. kAENeverInteract flag for the Apple event and, if so, returns an error. If not,
  6816. then the AEInteractWithUser function checks the server application’s preference
  6817. set by the AESetInteractionAllowed function and compares it against the source
  6818. of the Apple event—that is, whether it came from the same application, another
  6819. application or process on the same computer, or an application or process
  6820. running on another computer. AEInteractWithUser returns the
  6821. errAENoUserInteraction result code if the user-interaction preferences don’t
  6822. allow user interaction. If user interaction is allowed, the Apple Event Manager
  6823. brings your application to the front, either directly or by posting a
  6824. notification request. If AEInteractWithUser returns the noErr result code, then
  6825. your application is in the front and is free to interact with the user.
  6826.  
  6827.    Result code
  6828.           noErr                                               0           No
  6829.           error
  6830.           errAETimeout                       –1712          Apple event timed
  6831.           out
  6832.           errAENoUserInteraction    –1713          No user interaction allowed
  6833. _______________________________________________________________________________
  6834.  
  6835. æKY Requesting…More…Time…to…Respond…to…Apple…Events
  6836. æC »Requesting More Time to Respond to Apple Events                The Apple Event Manager
  6837. _______________________________________________________________________________
  6838.  
  6839. The AEResetTimer function resets the timeout value for an Apple event to its
  6840. starting value. A server application can call this function when it knows it
  6841. cannot fulfill a client application’s request (either by returning a result or
  6842. by sending back a reply Apple event) before the client application is due to
  6843. time out.
  6844.  
  6845. FUNCTION AEResetTimer (reply: AppleEvent) : OSErr;
  6846.  
  6847. The reply parameter is the default reply for an Apple event and is provided by
  6848. the Apple Event Manager. When AEResetTimer is called, the Apple Event Manager
  6849. uses the default reply to send a Reset Timer event to the client application;
  6850. the Apple Event Manager for the client application intercepts this Apple event
  6851. and resets the client application’s timer for the Apple event. (The Reset Timer
  6852. event is never dispatched to a handler, and the client application does not need
  6853. a handler for it.)
  6854.  
  6855.    Result code
  6856.           noErr                                       0           No error
  6857.           errAEReplyNotValid  –1709           AEResetTimer was passed an invalid
  6858.           reply
  6859. _______________________________________________________________________________
  6860.  
  6861. æKY Suspending…and…Resuming…Apple…Event…Handling
  6862. æC »Suspending and Resuming Apple Event Handling                   The Apple Event Manager
  6863. _______________________________________________________________________________
  6864.  
  6865. The AESuspendTheCurrentEvent function suspends the processing of the Apple event
  6866. that is currently being handled.
  6867.  
  6868. FUNCTION AESuspendTheCurrentEvent (theAppleEvent: AppleEvent) : OSErr;
  6869.  
  6870. The parameter theAppleEvent is the Apple event whose handling is to be
  6871. suspended. Although the Apple Event Manager doesn’t need the parameter
  6872. theAppleEvent to identify the Apple event currently being handled, providing
  6873. this parameter is a safeguard that ensures that you are suspending the correct
  6874. Apple event.
  6875.  
  6876. After a server application makes a successful call to the
  6877. AESuspendTheCurrentEvent function, it is no longer required to return a result
  6878. or a reply for the Apple event that was being handled. It can, however, return a
  6879. result if it later calls the AEResumeTheCurrentEvent function to resume event
  6880. processing.
  6881.  
  6882. The Apple Event Manager does not automatically dispose of Apple events that have
  6883. been suspended or of their default replies. (The Apple Event Manager does,
  6884. however, automatically dispose of a previously suspended Apple event and its
  6885. default reply if the server later resumes processing of the Apple event by
  6886. calling the AEResumeTheCurrentEvent function.) If your server application does
  6887. not resume processing of a suspended Apple event, it is responsible for using
  6888. the AEDisposeDesc function to dispose of both the Apple event and its default
  6889. reply when you are finished with them.
  6890.  
  6891.    Result code
  6892.           noErr                                       0           No error
  6893.  
  6894. The AEResumeTheCurrentEvent function informs the Apple Event Manager that your
  6895. application wants to resume the handling of a previously suspended Apple event
  6896. or that it has completed the handling of the Apple event.
  6897.  
  6898. FUNCTION AEResumeTheCurrentEvent (theAppleEvent, reply: AppleEvent; 
  6899.                                   dispatcher: EventHandlerProcPtr; 
  6900.                                   handlerRefcon: LongInt) : OSErr;
  6901.   
  6902. The parameter theAppleEvent is the Apple event whose processing is to be
  6903. resumed.
  6904.  
  6905. The reply parameter is the default reply that is automatically provided by the
  6906. Apple Event Manager for the Apple event.
  6907.  
  6908. The dispatcher parameter is one of the following:
  6909.  
  6910.   • a pointer to a routine for handling the event
  6911.  
  6912.   • the kAEUseStandardDispatch constant, which causes the Apple event to be 
  6913.      dispatched in the way it was when it was first received
  6914.  
  6915.   • the kAENoDispatch constant, which tells the Apple Event Manager that the 
  6916.      processing of the Apple event is complete and that it does not need to be 
  6917.      dispatched
  6918.  
  6919. If the value of the dispatcher parameter is not kAEUseStandardDispatch, the
  6920. handlerRefcon parameter is a reference constant that is passed to the handler
  6921. when the handler is called. If the value of the dispatcher parameter is
  6922. kAEUseStandardDispatch, the Apple Event Manager ignores the handlerRefcon
  6923. parameter and instead passes the reference constant that is stored in the Apple
  6924. event dispatch table entry for the Apple event. (If you want to pass the same
  6925. reference constant that is stored in the Apple event dispatch table, your
  6926. application can obtain the reference constant by calling the AEGetEventHandler
  6927. function.)
  6928.  
  6929.    Result code
  6930.           noErr                                       0           No error
  6931.  
  6932. The AESetTheCurrentEvent function specifies the Apple event to be handled. There
  6933. is generally no reason for your application to use this function. Instead of
  6934. calling this function, your application should let the Apple Event Manager go
  6935. through the dispatch tables to set the current Apple event.
  6936.  
  6937. FUNCTION AESetTheCurrentEvent (theAppleEvent: AppleEvent) : OSErr;
  6938.  
  6939. The parameter theAppleEvent is the Apple event that is to be handled.
  6940.  
  6941. The AESetTheCurrentEvent function is used only to avoid going through the
  6942. dispatch tables, and is used only in the following way:
  6943.  
  6944.    1.  An application suspends handling of an Apple event by calling the 
  6945.         AESuspendTheCurrentEvent function.
  6946.  
  6947.    2.  The application calls the AESetTheCurrentEvent function to inform the
  6948.    Apple
  6949.         Event Manager that it is handling the Apple event that was previously 
  6950.         suspended. It thereby makes the identity of the Apple event currently
  6951.         being 
  6952.         handled available to routines that call the AEGetTheCurrentEvent
  6953.         function.
  6954.  
  6955.    3.  The application handles the Apple event. When it is finished, it calls
  6956.    the 
  6957.         AEResumeTheCurrentEvent function with the value kAENoDispatch to tell 
  6958.         the Apple Event Manager that the processing of the event is complete and
  6959.         that 
  6960.          the Apple event does not need to be dispatched.
  6961.  
  6962.    Result code
  6963.           noErr                                       0           No error
  6964.  
  6965. The AEGetTheCurrentEvent function returns the Apple event that is currently
  6966. being handled. In many applications, the handling of an Apple event involves one
  6967. or more long chains of calls to routines within the application. The
  6968. AEGetTheCurrentEvent function makes it unnecessary for these calls to include
  6969. the current Apple event as a parameter; the routines can simply call
  6970. AEGetTheCurrentEvent to get the current Apple event when it is needed.
  6971.  
  6972. FUNCTION AEGetTheCurrentEvent (VAR theAppleEvent: AppleEvent) : 
  6973.                                OSErr;
  6974.  
  6975. This function returns the Apple event that is currently being handled in the
  6976. parameter theAppleEvent.
  6977.  
  6978.    Result code
  6979.           noErr                                       0           No error
  6980. _______________________________________________________________________________
  6981.  
  6982. æKY Creating…Apple…Events
  6983. æC »Creating Apple Events                                          The Apple Event Manager
  6984. _______________________________________________________________________________
  6985.  
  6986. The AECreateAppleEvent function creates an Apple event with several important
  6987. attributes but no parameters.
  6988.  
  6989. FUNCTION AECreateAppleEvent (theAEEventClass: AEEventClass; 
  6990.                              theAEEventID: AEEventID; target: 
  6991.                              AEAddressDesc; returnID: Integer; 
  6992.                              transactionID: LongInt; 
  6993.                              VAR result: AppleEvent) : OSErr;
  6994.  
  6995. The parameter theAEEventClass is the event class of the Apple event to be
  6996. created.
  6997.  
  6998. The parameter theAEEventID is the event ID of the Apple event to be created.
  6999.  
  7000. The target parameter is the address of the server application. See “Specifying a
  7001. Target Application” earlier in this chapter for information on how to address an
  7002. Apple event.
  7003.  
  7004. The returnID parameter is the return ID assigned to this Apple event; if the
  7005. kAutoGenerateReturnID constant is used as the value, the Apple Event Manager
  7006. assigns a return ID that is unique to the current session.
  7007.  
  7008. The transactionID parameter is the transaction ID for this Apple event. A
  7009. transaction refers to a sequence of Apple events that are sent back and forth
  7010. between the client and server applications, beginning with the client’s initial
  7011. request for a service. All Apple events that are part of a transaction must have
  7012. the same transaction ID.
  7013.  
  7014. The AECreateAppleEvent function returns in the result parameter the resulting
  7015. Apple event. Your application is responsible for using the AEDisposeDesc
  7016. function to dispose of the resulting Apple event once you are finished using it.
  7017.  
  7018. If the function returns a nonzero result code, a descriptor record with the
  7019. typeNull descriptor type is returned. A descriptor record of this type does not
  7020. contain any data.
  7021.  
  7022.    Result code
  7023.           noErr                                       0           No error
  7024.           memFullErr                    –108           Not enough room in heap
  7025.           zone
  7026. _______________________________________________________________________________
  7027.  
  7028. æKY Creating…and…Duplicating…Descriptor…Records
  7029. æC »Creating and Duplicating Descriptor Records                    The Apple Event Manager
  7030. _______________________________________________________________________________
  7031.  
  7032. The AECreateDesc function takes data and converts it into a descriptor record.
  7033.  
  7034. FUNCTION AECreateDesc (typeCode: DescType; dataPtr: Ptr; dataSize:
  7035.                        Size; VAR result: AEDesc) : OSErr;
  7036.  
  7037. The typeCode parameter is the descriptor type for the resulting descriptor
  7038. record.
  7039.  
  7040. The dataPtr parameter is a pointer to the data for the descriptor record.
  7041.  
  7042. The dataSize parameter is the length, in bytes, of the data for the descriptor
  7043. record.
  7044.  
  7045. The AECreateDesc function returns in the result parameter the resulting
  7046. descriptor record. This function creates a new descriptor record by copying the
  7047. descriptor record from the parameter. Your application is responsible for using
  7048. the AEDisposeDesc function to dispose of the resulting descriptor record once
  7049. you are finished using it.  You normally do this after receiving a result from
  7050. the AESend function.
  7051.  
  7052. If the function returns a nonzero result code, a descriptor record with the
  7053. typeNull descriptor type is returned. A descriptor record of this type does not
  7054. contain any data.
  7055.  
  7056.    Result code
  7057.           noErr                                       0           No error
  7058.           memFullErr                    –108           Not enough room in heap
  7059.           zone
  7060.  
  7061. The AEDuplicateDesc function makes a copy of a descriptor record.
  7062.  
  7063. FUNCTION AEDuplicateDesc (theAEDesc: AEDesc; VAR result: AEDesc) : 
  7064.                           OSErr;
  7065.  
  7066. The parameter theAEDesc is the descriptor record to be copied.
  7067.  
  7068. The AEDuplicateDesc function returns in the result parameter the resulting
  7069. descriptor record. This function creates a new descriptor record by copying the
  7070. descriptor record from the parameter. Your application is responsible for using
  7071. the AEDisposeDesc function to dispose of the resulting descriptor record once
  7072. you are finished using it. You normally do this after receiving a result from
  7073. the AESend function.
  7074.  
  7075. If the function returns a nonzero result code, a descriptor record with the
  7076. typeNull descriptor type is returned. A descriptor record of this type does not
  7077. contain any data.
  7078.  
  7079. It’s common for applications to send Apple events that have one or more
  7080. attributes or parameters in common. For example, if you’re sending a series of
  7081. Apple events to the same application, the address attribute is the same. In
  7082. these cases, the most efficient way to create the necessary Apple events is to
  7083. make a template Apple event that you can then copy—by calling the
  7084. AEDuplicateDesc function—as needed. You then fill in or change the remaining
  7085. parameters and attributes of the copy, send the copy by calling AESend, and then
  7086. dispose of the copy—by calling AEDisposeDesc—after AESend returns a result.
  7087.  
  7088.    Result code
  7089.           noErr                                       0           No error
  7090.           memFullErr                    –108           Not enough room in heap
  7091.           zone
  7092.  
  7093. _______________________________________________________________________________
  7094.  
  7095. æKY Creating…Descriptor…Lists…and…AE…Records
  7096. æC »Creating Descriptor Lists and AE Records                       The Apple Event Manager
  7097. _______________________________________________________________________________
  7098.  
  7099. The AECreateList function creates an empty descriptor list or AE record.
  7100.  
  7101. FUNCTION AECreateList (factoringPtr: Ptr; factoredSize: Size; isRecord:
  7102.                        Boolean; VAR resultList: AEDescList) : OSErr;
  7103.  
  7104. You can compress descriptor lists—thereby saving both space and, in some cases,
  7105. transmission time—by isolating data at the beginning of each descriptor record
  7106. that is the same for all descriptor records in the list. This common data is
  7107. sent only once for all the descriptor records in the list. When an application
  7108. gets descriptor records from a compressed descriptor list, the Apple Event
  7109. Manager automatically decompresses them.
  7110.  
  7111. The factoringPtr parameter is a pointer to the data at the beginning of each
  7112. descriptor that is the same for all descriptor records in the list. (The method
  7113. for compressing descriptor lists is analogous to extracting the common factor
  7114. from two or more numbers.) If there is no common data, or if you decide not to
  7115. isolate the common data, provide NIL as the value of the factoringPtr
  7116. parameter.
  7117.  
  7118. The factoredSize parameter is the size of the common data. If there is no common
  7119. data, or if you decide not to isolate the common data, the value of factoredSize
  7120. must be 0.
  7121.  
  7122. The isRecord parameter is a Boolean value that specifies the kind of list to
  7123. create. If you set its value to TRUE, the Apple Event Manager creates an AE
  7124. record. If you set its value to FALSE, the Apple Event Manager creates a
  7125. descriptor list.
  7126.  
  7127. The AECreateList  function returns in the resultList parameter the resulting
  7128. descriptor list or AE record. This function creates a new descriptor record by
  7129. copying the descriptor record from the parameter. Your application is
  7130. responsible for using the AEDisposeDesc function to dispose of the resulting
  7131. descriptor record once you are finished using it. You normally do this after
  7132. receiving a result from the AESend function.
  7133.  
  7134. If the function returns a nonzero result code, a descriptor record with the
  7135. typeNull descriptor type is returned. A descriptor record of this type does not
  7136. contain any data.
  7137.  
  7138.    Result code
  7139.           noErr                                       0           No error
  7140.           paramErr                            –50           Error in parameter
  7141.           list 
  7142.           memFullErr                    –108           Not enough room in heap
  7143.           zone
  7144. _______________________________________________________________________________
  7145.  
  7146. æKY Adding…Items…to…Descriptor…Lists
  7147. æC »Adding Items to Descriptor Lists                               The Apple Event Manager
  7148. _______________________________________________________________________________
  7149.  
  7150. The AEPutPtr function takes data specified in a buffer and converts it to a
  7151. descriptor record that it adds to a descriptor list.
  7152.  
  7153. FUNCTION AEPutPtr (theAEDescList: AEDescList; index: LongInt; typeCode:
  7154.                    DescType; dataPtr: Ptr; dataSize: Size) : OSErr;
  7155.  
  7156. The parameter theAEDescList is the descriptor list to which to add a descriptor
  7157. record.
  7158.  
  7159. The index parameter is the position in the list for the descriptor record (for
  7160. example, 2 specifies that it must be the second descriptor record). If there was
  7161. already a descriptor record at that position, it is replaced. If the value of
  7162. index is 0, the descriptor record is added at the end of the list.
  7163.  
  7164. The typeCode parameter is the descriptor type for the resulting descriptor
  7165. record.
  7166.  
  7167. The dataPtr parameter is a pointer to the data for the descriptor record.
  7168.  
  7169. The dataSize parameter is the length, in bytes, of the data for the descriptor
  7170. record.
  7171.  
  7172.    Result code
  7173.           noErr                                         0           No error
  7174.           memFullErr                      –108           Not enough room in heap
  7175.           zone
  7176.           errAEWrongDataType  –1703           Wrong descriptor type
  7177.           errAENotAEDesc           –1704           Not a valid descriptor record
  7178.           errAEBadListItem          –1705           Operation involving a list
  7179.           item failed
  7180.           errAEIllegalIndex           –1719           Not a valid list index
  7181.  
  7182. The AEPutDesc function adds a descriptor record to a descriptor list.
  7183.  
  7184. FUNCTION AEPutDesc (theAEDescList: AEDescList; index: LongInt; 
  7185.                     theAEDesc: AEDesc) : OSErr;
  7186.  
  7187. The parameter theAEDescList is the descriptor list to which you are adding a
  7188. descriptor record.
  7189.  
  7190. The index parameter is the position in the list for the descriptor record (for
  7191. example, 2 specifies that it must be the second descriptor record). If there was
  7192. already a descriptor record at that position, it is replaced. If the value of
  7193. index is 0, the descriptor record is added to the end of the list.
  7194.  
  7195. The parameter theAEDesc is the descriptor record to be added to the list.
  7196.  
  7197.    Result code
  7198.           noErr                                         0           No error
  7199.           memFullErr                      –108           Not enough room in heap
  7200.           zone
  7201.           errAEWrongDataType  –1703           Wrong descriptor type
  7202.           errAENotAEDesc           –1704           Not a valid descriptor record
  7203.           errAEBadListItem          –1705           Operation involving a list
  7204.           item failed
  7205.           errAEIllegalIndex           –1719           Not a valid list index
  7206.  
  7207. The AEPutArray function puts the data for an Apple event array into a descriptor
  7208. list.
  7209.  
  7210. FUNCTION AEPutArray (theAEDescList: AEDescList; arrayType: AEArrayType; 
  7211.                      arrayPtr: AEArrayDataPointer; itemType: DescType; 
  7212.                      itemSize: Size; itemCount: LongInt) : OSErr;
  7213.  
  7214. The parameter theAEDescList is the descriptor list into which to put the Apple
  7215. event array. If there are any items already in the descriptor list, they are
  7216. replaced.
  7217.  
  7218. The arrayType parameter is the Apple event array type to be created. This is
  7219. specified by one of the following constants: kAEDataArray, kAEPackedArray,
  7220. kAEHandleArray, kAEDescArray, or kAEKeyDescArray. The kAEDataArray constant
  7221. refers to an array of integers; kAEPackedArray refers to an array of characters;
  7222. kAEHandleArray refers to an array of handles; kAEDescArray refers to an array of
  7223. descriptor records; and kAEKeyDescArray refers to an array of keyword-specified
  7224. descriptor records.
  7225.  
  7226. If you are putting an array into a compressed descriptor list (see the
  7227. description of the AECreateList function for information about compressing
  7228. descriptor lists), the data for each array element must include the data that is
  7229. common to all the descriptor records in the list. The Apple Event Manager
  7230. automatically isolates the data you specified in the call to AECreateList that
  7231. is common to all the elements of the array.
  7232.  
  7233. The arrayPtr parameter is a pointer to the buffer containing the array.
  7234.  
  7235. For packed, data, and handle arrays, the itemType parameter specifies the
  7236. descriptor type of array items to be created.
  7237.  
  7238. For packed and data arrays, the itemSize parameter specifies the size, in bytes,
  7239. of the array items to be created.
  7240.  
  7241. The itemCount parameter is the number of elements in the array.
  7242.  
  7243.    Result code
  7244.           noErr                                         0           No error
  7245.           memFullErr                      –108           Not enough room in heap
  7246.           zone
  7247.           errAEWrongDataType  –1703           Wrong descriptor type
  7248.           errAENotAEDesc           –1704           Not a valid descriptor record
  7249. _______________________________________________________________________________
  7250.  
  7251. æKY Adding…Data…to…AE…Records
  7252. æC »Adding Data to AE Records                                      The Apple Event Manager
  7253. _______________________________________________________________________________
  7254.  
  7255. The AEPutKeyPtr function takes a pointer to data, a descriptor type, and a
  7256. keyword and converts them into a keyword-specified descriptor record that it
  7257. adds to an AE record.
  7258.  
  7259. FUNCTION AEPutKeyPtr (theAERecord: AERecord; theAEKeyword: AEKeyword; 
  7260.                       typeCode: DescType; dataPtr: Ptr; dataSize: 
  7261.                       Size) : OSErr;
  7262.  
  7263. The parameter theAERecord is the AE record to which to add a keyword-specified
  7264. descriptor record.
  7265.  
  7266. The parameter theAEKeyword is the keyword specifying the descriptor record. If
  7267. there was already a descriptor record with this keyword, it is replaced.
  7268.  
  7269. The typeCode parameter is the descriptor type for the keyword-specified
  7270. descriptor record.
  7271.  
  7272. The dataPtr parameter is a pointer to the data for the keyword-specified
  7273. descriptor record.
  7274.  
  7275. The dataSize parameter is the length, in bytes, of the data for the
  7276. keyword-specified descriptor record.
  7277.  
  7278.    Result codes
  7279.           noErr                                             0        No error
  7280.           memFullErr                          –108        Not enough room in
  7281.           heap zone
  7282.           errAEWrongDataType      –1703        Wrong descriptor type
  7283.           errAENotAEDesc               –1704         Not a valid descriptor
  7284.           record
  7285.           errAEBadListItem              –1705         Operation involving a list
  7286.           item failed
  7287.  
  7288. The AEPutKeyDesc function takes a descriptor record and a keyword and converts
  7289. them into a keyword-specified descriptor record that it adds to an AE record.
  7290.  
  7291. FUNCTION AEPutKeyDesc (theAERecord: AERecord; theAEKeyword: AEKeyword; 
  7292.                        theAEDesc: AEDesc) : OSErr;
  7293.  
  7294. The parameter theAERecord is the AE record to which to add the keyword-specified
  7295. descriptor record.
  7296.  
  7297. The parameter theAEKeyword is the keyword specifying the descriptor record. If
  7298. there was already a keyword-specified descriptor record with this keyword, it is
  7299. replaced.
  7300.  
  7301. The parameter theAEDesc is the descriptor record for the keyword-specified
  7302. descriptor record.
  7303.  
  7304.    Result codes
  7305.           noErr                                             0        No error
  7306.           memFullErr                          –108        Not enough room in
  7307.           heap zone
  7308.           errAEWrongDataType      –1703        Wrong descriptor type
  7309.           errAENotAEDesc               –1704         Not a valid descriptor
  7310.           record
  7311.           errAEBadListItem              –1705         Operation involving a list
  7312.           item failed
  7313. _______________________________________________________________________________
  7314.  
  7315. æKY Adding…Parameters…and…Attributes…to…Apple…Events
  7316. æC »Adding Parameters and Attributes to Apple Events               The Apple Event Manager
  7317. _______________________________________________________________________________
  7318.  
  7319. The AEPutParamPtr function takes a pointer to data, a descriptor type, and a
  7320. keyword and converts them into a parameter that it adds to an Apple event.
  7321.  
  7322. FUNCTION AEPutParamPtr (theAppleEvent: AppleEvent; theAEKeyword: 
  7323.                         AEKeyword; typeCode: DescType; dataPtr: Ptr; 
  7324.                         dataSize: Size) : OSErr;
  7325.  
  7326. The parameter theAppleEvent is the Apple event to which you are adding a
  7327. parameter.
  7328.  
  7329. The parameter theAEKeyword is the keyword for the parameter. If there was
  7330. already a parameter with this keyword in the Apple event, it is replaced.
  7331.  
  7332. The typeCode parameter is the descriptor type for the parameter.
  7333.  
  7334. The dataPtr parameter is a pointer to the data for the parameter.
  7335.  
  7336. The dataSize parameter is the length, in bytes, of the data for the parameter.
  7337.  
  7338.    Result codes
  7339.           noErr                                             0        No error
  7340.           memFullErr                          –108        Not enough room in
  7341.           heap zone
  7342.           errAEWrongDataType      –1703        Wrong descriptor type
  7343.           errAENotAEDesc               –1704         Not a valid descriptor
  7344.           record
  7345.           errAEBadListItem              –1705         Operation involving a list
  7346.           item failed
  7347.  
  7348. The AEPutParamDesc function takes a descriptor record, and a keyword and
  7349. converts them into a parameter that it adds to an Apple event.
  7350.  
  7351. FUNCTION AEPutParamDesc (theAppleEvent: AppleEvent; theAEKeyword: 
  7352.                          AEKeyword; theAEDesc: AEDesc) : OSErr;
  7353.  
  7354. The parameter theAppleEvent is the Apple event to which you are adding a
  7355. parameter.
  7356.  
  7357. The parameter theAEKeyword is the keyword for the parameter. If there was
  7358. already a parameter with this keyword in the Apple event, it is replaced.
  7359.  
  7360. The parameter theAEDesc is the descriptor record for the parameter.
  7361.  
  7362.    Result codes
  7363.           noErr                                             0        No error
  7364.           memFullErr                          –108        Not enough room in
  7365.           heap zone
  7366.           errAEWrongDataType      –1703        Wrong descriptor type
  7367.           errAENotAEDesc               –1704         Not a valid descriptor
  7368.           record
  7369.           errAEBadListItem              –1705         Operation involving a list
  7370.           item failed
  7371.  
  7372. The AEPutAttributePtr function takes a pointer to data, a descriptor type, and a
  7373. keyword and converts them into an attribute that it adds to an Apple event.
  7374.  
  7375. FUNCTION AEPutAttributePtr (theAppleEvent: AppleEvent; theAEKeyword: 
  7376.                             AEKeyword; typeCode: DescType; dataPtr: 
  7377.                             Ptr; dataSize: Size) : OSErr;
  7378.  
  7379. The parameter theAppleEvent is the Apple event to which you are adding an
  7380. attribute.
  7381.  
  7382. The parameter theAEKeyword is the keyword of the attribute. If there was already
  7383. an attribute with this keyword in the Apple event, it is replaced.
  7384.  
  7385. The typeCode parameter is the descriptor type for the attribute.
  7386.  
  7387. The dataPtr parameter is a pointer to the buffer containing the data to be
  7388. assigned to the attribute.
  7389.  
  7390. The dataSize parameter is the length, in bytes, of the data to be assigned to
  7391. the attribute.
  7392.  
  7393.    Result codes
  7394.           noErr                                             0        No error
  7395.           memFullErr                          –108        Not enough room in
  7396.           heap zone
  7397.           errAECoercionFail             –1700        Data could not be coerced
  7398.           to the requested 
  7399.  
  7400.                                                                             type
  7401.           errAENotAEDesc               –1704         Not a valid descriptor
  7402.           record
  7403.  
  7404. The AEPutAttributeDesc takes a descriptor record and a keyword and converts them
  7405. into an attribute that it adds to an Apple event.
  7406.  
  7407. FUNCTION AEPutAttributeDesc (theAppleEvent: AppleEvent; theAEKeyword: 
  7408.                              AEKeyword; theAEDesc: AEDesc) : OSErr;
  7409.  
  7410. The parameter theAppleEvent is the Apple event to which you are adding an
  7411. attribute.
  7412.  
  7413. The parameter theAEKeyword is the keyword of the attribute. If there was already
  7414. an attribute with this keyword in the Apple event, it is replaced.
  7415.  
  7416. The parameter theAEDesc is the descriptor record to be assigned to the
  7417. attribute. The descriptor type of the specified descriptor record should match
  7418. the defined descriptor type for that attribute. For example, the
  7419. keyEventSourceAttr attribute has the typeShortInteger descriptor type.
  7420.  
  7421. If the descriptor type required for the attribute is different than the
  7422. descriptor type of the descriptor record, the Apple Event Manager attempts to
  7423. coerce the descriptor record into the required type, with one exception: the
  7424. Apple Event Manager does not attempt to coerce the data for an address
  7425. attribute, thereby allowing applications to use their own address types.
  7426.  
  7427.    Result codes
  7428.           noErr                                             0        No error
  7429.           memFullErr                          –108        Not enough room in
  7430.           heap zone
  7431.           errAECoercionFail             –1700        Data could not be coerced
  7432.           to the requested 
  7433.  
  7434.                                                                             type
  7435.           errAENotAEDesc               –1704         Not a valid descriptor
  7436.           record
  7437. _______________________________________________________________________________
  7438.  
  7439. æKY Sending…Apple…Events
  7440. æC »Sending Apple Events                                           The Apple Event Manager
  7441. _______________________________________________________________________________
  7442.  
  7443. The AESend function sends an Apple event.
  7444.  
  7445. FUNCTION AESend (theAppleEvent: AppleEvent; VAR reply: AppleEvent; 
  7446.                  sendMode: AESendMode; sendPriority: AESendPriority; 
  7447.                  timeOutInTicks: LongInt; idleProc: IdleProcPtr; 
  7448.                  filterProc: EventFilterProcPtr) : OSErr;
  7449.  
  7450. The parameter theAppleEvent specifies the Apple event to be sent.
  7451.  
  7452. The reply parameter specifies the reply Apple event that is returned if you
  7453. specify the kAEWaitReply flag in the sendMode parameter. (If you specify the
  7454. kAEQueueReply flag in the sendMode parameter, you receive the reply Apple event
  7455. in your event queue.) If you specify either the kAEQueueReply flag or the
  7456. kAENoReply flag, the data in the reply Apple event returned by this function is
  7457. not valid. If this function returns a nonzero result, it also returns in the
  7458. reply parameter a descriptor record whose descriptor type is typeNull—that is,
  7459. one that does not contain data. If you specify kAEWaitReply, your application is
  7460. responsible for using the AEDisposeDesc function to dispose of the resulting
  7461. descriptor record.
  7462.  
  7463. The sendMode parameter allows you to specify the following: the reply mode for
  7464. the Apple event (set with one of the constants kAENoReply, kAEQueueReply, or
  7465. kAEWaitReply); the interaction mode (set with one of the constants
  7466. kAENeverInteract, kAECanInteract, or kAEAlwaysInteract); the layer switch mode
  7467. (set with the kAECanSwitchLayer constant); the reconnection mode (set with the
  7468. kAEDontReconnect constant); and the return receipt mode (set with the
  7469. kAEWantReceipt constant). You obtain the value for this parameter by adding the
  7470. appropriate constants. These flags are stored in the interaction level
  7471. attribute, whose keyword is keyInteractLevelAttr. The sendMode flags are
  7472. described in a later part of this section.
  7473.  
  7474. In the sendPriority parameter, you specify flags that determine whether the
  7475. Apple event is put at the back of the event queue (the kAENormalPriority flag)
  7476. or at the front of the queue (the kAEHighPriority flag).
  7477.  
  7478. If the reply mode specified in the sendMode parameter is kAEWaitReply, or if a
  7479. return receipt is requested, the timeOutInTicks parameter specifies the length
  7480. of time (in ticks) that the client application is willing to wait for the reply
  7481. or return receipt from the server application before timing out. Most
  7482. applications should use the kAEDefaultTimeout constant, which tells the Apple
  7483. Event Manager to provide an appropriate timeout duration. If the value of this
  7484. parameter is kNoTimeOut, the Apple event never times out.
  7485.  
  7486. The idleProc parameter specifies a pointer to a function for any tasks (such as
  7487. displaying a wristwatch or spinning beach ball cursor) that the application
  7488. performs while waiting for a reply or a return receipt (see “Writing an Idle
  7489. Function” earlier in this chapter).
  7490.  
  7491. The filterProc parameter specifies a pointer to a routine that accepts certain
  7492. incoming Apple events that are received while the handler waits for a reply or a
  7493. return receipt and filters out the rest (see “Writing a Reply Filter Function”
  7494. earlier in this chapter).
  7495.  
  7496. You can use one of the following flags in the sendMode parameter to specify the
  7497. reply mode for an Apple event. Only one of these flags may be set.
  7498.  
  7499. Flag                                Description
  7500.  
  7501. kAENoReply               Your application does not want a reply Apple event; the
  7502.  
  7503.                                         server processes your Apple event as
  7504.                                         soon as it has the 
  7505.                                         opportunity.
  7506.  
  7507. kAEQueueReply         Your application wants a reply Apple event; the reply
  7508. appears
  7509.                                          in your event queue as soon as the
  7510.                                          server has the 
  7511.                                          opportunity to process and respond to
  7512.                                          your Apple event.
  7513.  
  7514. kAEWaitReply            Your application wants a reply Apple event and is
  7515. willing to 
  7516.                                          give up the processor while waiting for
  7517.                                          the reply; for 
  7518.                                          example, if the server application is
  7519.                                          on the same computer as
  7520.                                          your application, your application
  7521.                                          yields the processor to 
  7522.                                          allow the server to respond to your
  7523.                                          Apple event.
  7524.  
  7525. You can communicate your user-interaction preferences to the server by
  7526. specifying one of these flags in the sendMode parameter of the AESend function.
  7527. Only one of these flags may be set.
  7528.  
  7529. Flag                                Description
  7530.  
  7531. kAENeverInteract      The server application should never interact with the user
  7532. in
  7533.                                          response to this Apple event. If this
  7534.                                          flag is set, 
  7535.                                          AEInteractWithUser does not bring the
  7536.                                          server application to 
  7537.                                          the foreground (this is the default
  7538.                                          when an Apple event is 
  7539.                                          sent to a remote application).
  7540.  
  7541. kAECanInteract           The server application can interact with the user in
  7542. response 
  7543.                                          to this Apple event—by convention, if
  7544.                                          the user needs to 
  7545.                                           supply information to the server. If
  7546.                                           this flag is set and the 
  7547.                                           server allows interaction,
  7548.                                           AEInteractWithUser brings the 
  7549.                                           server application to the foreground
  7550.                                           (this is the default 
  7551.                                           when an Apple event is sent to a local
  7552.                                           application).
  7553.  
  7554. kAEAlwaysInteract     The server application can interact with the user in
  7555. response 
  7556.                                          to this Apple event—by convention, even
  7557.                                          if no information 
  7558.                                          is needed from the user. If this flag
  7559.                                          is set and the server 
  7560.                                          allows interaction, AEInteractWithUser
  7561.                                          brings the server 
  7562.                                          application to the foreground. The
  7563.                                          Apple Event Manager 
  7564.                                          does not distinguish between this flag
  7565.                                          and the 
  7566.                                          kAECanInteract flag—distinguishing
  7567.                                          between them is the
  7568.                                          responsibility of the server
  7569.                                          application.
  7570.  
  7571. The flags in the following list specify the layer switch mode, the reconnection
  7572. mode, and the return receipt mode. Any of these flags may be set.
  7573.  
  7574. Flag                                 Description
  7575.  
  7576. kAECanSwitchLayer     If both the client and server allow interaction and this
  7577. flag 
  7578.                                            is set, AEInteractWithUser brings the
  7579.                                            server directly to the 
  7580.                                            foreground if adherence to the
  7581.                                            principle of user control 
  7582.                                            allows. If the action would be
  7583.                                            contrary to this principle, 
  7584.                                            AEInteractWithUser uses the
  7585.                                            Notification Manager to 
  7586.                                            request that user bring the server
  7587.                                            application to the 
  7588.                                            foreground. If both the client and
  7589.                                            server allow interaction 
  7590.                                            and this flag is not set,
  7591.                                            AEInteractWithUser always uses the 
  7592.                                            Notification Manager to request that
  7593.                                            the user bring the 
  7594.                                            server application to the foreground.
  7595.  
  7596. kAEDontReconnect      Specifies that the Apple Event Manager must not 
  7597.                                            automatically try to reconnect if it
  7598.                                            receives a sessClosedErr 
  7599.                                            result code from the PPC Toolbox.
  7600.  
  7601. kAEWantReceipt          The sender wants to receive a return receipt for this
  7602. Apple 
  7603.                                            event from the Event Manager.
  7604.                                            (Getting a return receipt 
  7605.                                            means only that the receiving
  7606.                                            application accepted the 
  7607.                                            Apple event; the Apple event may or
  7608.                                            may not be handled 
  7609.                                            successfully after it is accepted).
  7610.                                            If the receiving application 
  7611.                                            does not send a return receipt before
  7612.                                            the request times out, 
  7613.                                            AESend returns errAETimeout as its
  7614.                                            function result.
  7615.  
  7616. If the Apple Event Manager cannot find a handler for an Apple event in either
  7617. the application or system Apple event dispatch table, it returns the result code
  7618. errAEEventNotHandled to the server application (as the result of the
  7619. AEProcessAppleEvent function). If the client is waiting for a reply, the Apple
  7620. Event Manager also returns this result code to the client.
  7621.  
  7622. AESend returns noErr as the function result if the Apple event was successfully
  7623. sent by the Event Manager. A noErr result from AESend does not indicate that the
  7624. Apple event was handled successfully; it only indicates that the Apple event was
  7625. successfully sent by the Event Manager. If a result code other than noErr is
  7626. returned by the handler, and if the client is waiting for a reply, it is
  7627. returned in the keyErrorNumber parameter of the reply Apple event.
  7628.  
  7629.    Result codes
  7630.           noErr                                                       0      No
  7631.           error
  7632.           memFullErr                                    –108      Not enough
  7633.           room in heap zone
  7634.           connectionInvalid                         –609      Connection is
  7635.           invalid
  7636.           errAEEventNotHandled            –1708      Event wasn’t handled by an
  7637.           Apple 
  7638.                                                                                
  7639.                                                                                
  7640.  
  7641.           errAEUnknownSendMode       –1710      Invalid sending mode was passed
  7642.           errAEWaitCanceled                     –1711      User canceled out of
  7643.           wait loop for 
  7644.                                                                                
  7645.                                                                                
  7646.                                                                                
  7647.  
  7648.           errAETimeout                              –1712      Apple event timed
  7649.           out
  7650.           errAEUnknownAddressType   –1716      Unknown Apple event address type
  7651. _______________________________________________________________________________
  7652.  
  7653. æKY Getting…the…Sizes…and…Descriptor…Types…of…Descriptor…Records
  7654. æC »Getting the Sizes and Descriptor Types of Descriptor Records   The Apple Event Manager
  7655. _______________________________________________________________________________
  7656.  
  7657. The AESizeOfNthItem function returns the size and descriptor type of a
  7658. descriptor record in a descriptor list.
  7659.  
  7660. FUNCTION AESizeOfNthItem (theAEDescList: AEDescList; index: LongInt; 
  7661.                           VAR typeCode: DescType; VAR dataSize: Size) 
  7662.                           : OSErr;
  7663.  
  7664. The parameter theAEDescList is the descriptor list containing the descriptor
  7665. record.
  7666.  
  7667. The index parameter is the position of the descriptor record in the list (for
  7668. example, 2 specifies the second descriptor record).
  7669.  
  7670. The AESizeOfNthItem function returns the descriptor type of the descriptor
  7671. record in the typeCode parameter .
  7672.  
  7673. This function returns the length, in bytes, of the data contained in the
  7674. descriptor record in the dataSize parameter.
  7675.  
  7676.    Result codes
  7677.           noErr                                              0      No error
  7678.           errAEDescNotFound          –1701      Descriptor record was not found
  7679.           errAEReplyNotArrived    –1718       Reply has not yet arrived
  7680.  
  7681. The AESizeOfKeyDesc function returns the size and descriptor type of a
  7682. keyword-specified descriptor record in an AE record.
  7683.  
  7684. FUNCTION AESizeOfKeyDesc (theAERecord: AERecord; theAEKeyword: 
  7685.                           AEKeyword; VAR typeCode: DescType; 
  7686.                           VAR dataSize: Size) : OSErr;
  7687.  
  7688. The parameter theAERecord is the AE record containing the desired
  7689. keyword-specified descriptor record.
  7690.  
  7691. The parameter theAEKeyword is the keyword that specifies the desired descriptor
  7692. record.
  7693.  
  7694. This function returns the descriptor type of the desired keyword-specified
  7695. descriptor record in the typeCode parameter.
  7696.  
  7697. This function returns the length, in bytes, of the data contained in the
  7698. keyword-specified descriptor record in the dataSize parameter.
  7699.  
  7700.    Result codes
  7701.           noErr                                               0      No error
  7702.           errAEDescNotFound           –1701      Descriptor record was not found
  7703.           errAENotAEDesc                 –1704      Not a valid descriptor
  7704.           record
  7705.           errAEReplyNotArrived     –1718       Reply has not yet arrived
  7706.  
  7707. The AESizeOfParam function returns the size and descriptor type of an Apple
  7708. event parameter.
  7709.  
  7710. FUNCTION AESizeOfParam (theAppleEvent: AppleEvent; theAEKeyword: 
  7711.                         AEKeyword; VAR typeCode: DescType; 
  7712.                         VAR dataSize: Size) : OSErr;
  7713.  
  7714. The parameter theAppleEvent is the Apple event containing the parameter.
  7715.  
  7716. The parameter theAEKeyword is the keyword that specifies the desired parameter.
  7717.  
  7718. The function returns the descriptor type of the parameter in the typeCode
  7719. parameter.
  7720.  
  7721. The function returns the length, in bytes, of the data contained in the desired
  7722. parameter in the dataSize parameter.
  7723.  
  7724.    Result codes
  7725.           noErr                                               0      No error
  7726.           errAEDescNotFound           –1701      Descriptor record was not found
  7727.           errAENotAEDesc                 –1704      Not a valid descriptor
  7728.           record
  7729.           errAEReplyNotArrived     –1718       Reply has not yet arrived
  7730.  
  7731. The AESizeOfAttribute function returns the size and descriptor type of an Apple
  7732. event attribute.
  7733.  
  7734. FUNCTION AESizeOfAttribute (theAppleEvent: AppleEvent; theAEKeyword: 
  7735.                             AEKeyword; VAR typeCode: DescType; 
  7736.                             VAR dataSize: Size) : OSErr;
  7737.  
  7738. The parameter theAppleEvent is the Apple event containing the attribute.
  7739.  
  7740. The parameter theAEKeyword is the keyword that specifies the attribute.
  7741.  
  7742. The function returns the descriptor type of the attribute in the typeCode
  7743. parameter.
  7744.  
  7745. The function returns the length, in bytes, of the data contained in the
  7746. attribute in the dataSize parameter.
  7747.  
  7748.    Result codes
  7749.           noErr                                               0      No error
  7750.           errAEDescNotFound           –1701      Descriptor record was not found
  7751.           errAENotAEDesc                 –1704      Not a valid descriptor
  7752.           record
  7753.           errAEReplyNotArrived     –1718       Reply has not yet arrived
  7754. _______________________________________________________________________________
  7755.  
  7756. æKY Deleting…Descriptor…Records
  7757. æC »Deleting Descriptor Records                                    The Apple Event Manager
  7758. _______________________________________________________________________________
  7759.  
  7760. The AEDeleteItem function deletes a descriptor record from a descriptor list.
  7761.  
  7762. FUNCTION AEDeleteItem (theAEDescList: AEDescList; index: LongInt) : 
  7763.                        OSErr;
  7764.  
  7765. The parameter theAEDescList is the descriptor list containing the descriptor
  7766. record to be deleted.
  7767.  
  7768. The index parameter is the position of the descriptor record to delete (for
  7769. example, 2 specifies the second item).
  7770.  
  7771.    Result codes
  7772.           noErr                                               0      No error
  7773.           errAEDescNotFound           –1701      Descriptor record was not found
  7774.           errAENotAEDesc                 –1704      Not a valid descriptor
  7775.           record
  7776.           errAEBadListItem                –1705      Operation involving a list
  7777.           item failed
  7778.  
  7779. The AEDeleteKeyDesc function deletes a keyword-specified descriptor record from
  7780. an AE record.
  7781.  
  7782. FUNCTION AEDeleteKeyDesc (theAERecord: AERecord; theAEKeyword: 
  7783.                           AEKeyword) : OSErr;
  7784.  
  7785. The parameter theAERecord is the AE record containing the keyword-specified
  7786. descriptor record to be deleted.
  7787.  
  7788. The parameter theAEKeyword is the keyword that specifies the descriptor record
  7789. to be deleted.
  7790.  
  7791.    Result codes
  7792.           noErr                                               0      No error
  7793.           errAEDescNotFound           –1701      Descriptor record was not found
  7794.           errAENotAEDesc                 –1704      Not a valid descriptor
  7795.           record
  7796.           errAEBadListItem                –1705      Operation involving a list
  7797.           item failed
  7798.  
  7799. The AEDeleteParam function deletes an Apple event parameter.
  7800.  
  7801. FUNCTION AEDeleteParam (theAppleEvent: AppleEvent; theAEKeyword: 
  7802.                         AEKeyword) : OSErr;
  7803.  
  7804. The parameter theAppleEvent is the Apple event containing the parameter to be
  7805. deleted.
  7806.  
  7807. The parameter theAEKeyword is the keyword that specifies the parameter to be
  7808. deleted.
  7809.  
  7810.    Result codes
  7811.           noErr                                               0      No error
  7812.           errAEDescNotFound           –1701      Descriptor record was not found
  7813.           errAENotAEDesc                 –1704      Not a valid descriptor
  7814.           record
  7815.           errAEBadListItem                –1705      Operation involving a list
  7816.           item failed
  7817. _______________________________________________________________________________
  7818.  
  7819. æKY Deallocating…Memory…for…Descriptor…Records
  7820. æC »Deallocating Memory for Descriptor Records                     The Apple Event Manager
  7821. _______________________________________________________________________________
  7822.  
  7823. The AEDisposeDesc function deallocates the memory used by a descriptor record.
  7824. Because all Apple event structures (except for keyword-specified descriptor
  7825. records) are descriptor records, you can use AEDisposeDesc for any of them.
  7826.  
  7827. FUNCTION AEDisposeDesc (VAR theAEDesc: AEDesc) : OSErr;
  7828.  
  7829. The parameter theAEDesc is the descriptor record to deallocate.
  7830.  
  7831.    Result codes
  7832.           noErr                                               0      No error
  7833. _______________________________________________________________________________
  7834.  
  7835. æKY Coercing…Descriptor…Types
  7836. æC »Coercing Descriptor Types                                      The Apple Event Manager
  7837. _______________________________________________________________________________
  7838.  
  7839. <Intro section  here? Why use these, and so on>
  7840. The AECoercePtr function takes a pointer to data and a desired descriptor type
  7841. and attempts to coerce the data into the desired descriptor type. If successful,
  7842. it creates a descriptor record containing the newly coerced data.
  7843.  
  7844. FUNCTION AECoercePtr (typeCode: DescType; dataPtr: Ptr; dataSize: Size;
  7845.                       toType: DescType; VAR result: AEDesc) : OSErr;
  7846.  
  7847. The typeCode parameter is the descriptor type of the source data.
  7848.  
  7849. The dataPtr parameter is a pointer to the data to be coerced.
  7850.  
  7851. The dataSize parameter is the length, in bytes, of the data to be coerced.
  7852.  
  7853. The toType parameter is the desired descriptor type of the resulting descriptor
  7854. record.
  7855.  
  7856. The AECoercePtr function function returns in the result parameter the resulting
  7857. descriptor record. This function creates a new descriptor record by copying the
  7858. descriptor record from the parameter. Your application is responsible for using
  7859. the AEDisposeDesc function to dispose of the resulting descriptor record once
  7860. you are finished using it.
  7861.  
  7862. If the function returns a nonzero result code, a descriptor record with the
  7863. typeNull descriptor type is returned. A descriptor record of this type does not
  7864. contain any data.
  7865.  
  7866.    Note: To avoid infinite recursion, AECoercePtr must never be called by an 
  7867.    application-supplied coercion routine.
  7868.  
  7869.    Result codes
  7870.           noErr                                      0      No error
  7871.           memFullErr                   –108      Not enough room in heap zone
  7872.           errAECoercionFail      –1700      Data could not be coerced to the
  7873.           requested 
  7874.  
  7875. The AECoerceDesc function coerces the data in a descriptor record to another
  7876. descriptor type.
  7877.  
  7878. FUNCTION AECoerceDesc (theAEDesc: AEDesc; toType: DescType; VAR result:
  7879.                        AEDesc) : OSErr;
  7880.  
  7881. The parameter theAEDesc is the descriptor record whose data is to be coerced.
  7882.  
  7883. The toType parameter is the desired descriptor type of the resulting descriptor
  7884. record.
  7885.  
  7886. The AECoerceDesc function returns in the result parameter the resulting
  7887. descriptor record. This function creates a new descriptor record by copying the
  7888. descriptor record from the parameter. Your application is responsible for using
  7889. the AEDisposeDesc function to dispose of the resulting descriptor record once
  7890. you are finished using it.
  7891.  
  7892. If the function returns a nonzero result code, a descriptor record with the
  7893. typeNull descriptor type is returned. A descriptor record of this type does not
  7894. contain any data.
  7895.  
  7896.    Note: To avoid infinite recursion, AECoerceDesc must never be called by an
  7897.    application-supplied coercion routine.
  7898.  
  7899.    Result codes
  7900.           noErr                                      0      No error
  7901.           memFullErr                   –108      Not enough room in heap zone
  7902.           errAECoercionFail      –1700      Data could not be coerced to the
  7903.           requested 
  7904.                                                                    descriptor
  7905.                                                                    type
  7906. _______________________________________________________________________________
  7907.  
  7908. æKY Creating…and…Managing…the…Coercion…Handler…Tables
  7909. æC »Creating and Managing the Coercion Handler Tables              The Apple Event Manager
  7910. _______________________________________________________________________________
  7911.  
  7912. The AEInstallCoercionHandler function installs a coercion handler routine in
  7913. either the application or system coercion table.
  7914.  
  7915. FUNCTION AEInstallCoercionHandler (fromType: DescType; toType: DescType; 
  7916.                                    handler: ProcPtr; handlerRefcon: 
  7917.                                    LongInt; fromTypeIsDesc: Boolean; 
  7918.                                    isSysHandler: Boolean) : OSErr;
  7919.  
  7920. The fromType parameter is the descriptor type of the data coerced by the
  7921. handler, and the toType parameter is the descriptor type of the resulting data.
  7922. If there was already an entry in the specified coercion handler table for the
  7923. same source descriptor type and result descriptor type, it is replaced.
  7924.  
  7925. Therefore, before installing a handler for a particular descriptor type into the
  7926. system coercion table, use the AEGetCoercionHandler function to determine if the
  7927. table already contains a handler for that descriptor type. If an entry exists,
  7928. AEGetCoercionHandler returns a reference constant and a pointer to that handler.
  7929. Chain these to your coercion handler by providing pointers to the previous
  7930. handler and its reference constant in the handlerRefcon parameter of
  7931. AEInstallCoercionHandler. When your handler is finished, use these pointers to
  7932. call the previous handler.
  7933.  
  7934. The handler parameter is a pointer to the coercion handler routine. Note that a
  7935. handler in the system coercion table must reside in the system heap; this means
  7936. that if the value of the isSysHandler parameter is TRUE, the handler parameter
  7937. must point to a location in the system heap.
  7938.  
  7939. The handlerRefcon parameter is a reference constant that is passed by the Apple
  7940. Event Manager to the handler each time the handler is called. If your handler
  7941. doesn’t expect a reference constant, use 0 as the value of this parameter.
  7942.  
  7943. The fromTypeIsDesc parameter specifies the form of the data to be coerced. If
  7944. its value is TRUE, the coercion handler expects the data to be passed as a
  7945. descriptor record. If its value is FALSE, the coercion handler expects a pointer
  7946. to the data to be coerced. Because it is more efficient for the Apple Event
  7947. Manager to provide a pointer to data than to a descriptor record, all coercion
  7948. routines should accept a pointer to data if possible.
  7949.  
  7950. The isSysHandler parameter specifies the coercion table to which to add the
  7951. handler. If its value is TRUE, the handler is added to the system coercion table
  7952. and made available to all applications. If its value is FALSE, the handler is
  7953. added to the application coercion table. Note that a handler in the system
  7954. coercion table must reside in the system heap; this means that if the value of
  7955. the isSysHandler parameter is TRUE, the handler parameter must point to a
  7956. location in the system heap.
  7957.  
  7958. If you put your handler code in the system heap or in your own heap, use the
  7959. AERemoveCoercionHandler function to remove the handler when your application
  7960. quits.
  7961.  
  7962.    Note: When an application calls a system Apple event handler, the A5 register
  7963.    is 
  7964.    set up for the calling application. For this reason, if you provide a system
  7965.    Apple 
  7966.    event handler, it should never use A5 global variables or anything that
  7967.    depends 
  7968.    on a particular context; otherwise, the application that calls the system
  7969.    handler 
  7970.    may crash.
  7971.  
  7972.    Result codes
  7973.           noErr                                      0      No error
  7974.           memFullErr                   –108      Not enough room in heap zone
  7975.  
  7976. The AEGetCoercionHandler function returns the handler for a specified descriptor
  7977. type coercion.
  7978.  
  7979. FUNCTION AEGetCoercionHandler (fromType: DescType; toType: DescType; 
  7980.                                VAR handler: ProcPtr; VAR handlerRefcon: 
  7981.                                LongInt; VAR fromTypeIsDesc: Boolean; 
  7982.                                isSysHandler: Boolean) : OSErr;
  7983.  
  7984. The fromType parameter is the descriptor type of the data coerced by the
  7985. handler, while the parameter toType is the descriptor type of the resulting
  7986. data.
  7987.  
  7988. The function returns a pointer to the coercion handler routine in the handler
  7989. parameter.
  7990.  
  7991. The function returns a reference constant in the handlerRefcon parameter. The
  7992. Apple Event Manager passes this reference constant to the handler each time the
  7993. handler is called.
  7994.  
  7995. If the function returns TRUE in the fromTypeIsDesc parameter, the coercion
  7996. handler expects the data to be passed as a descriptor record. If the function
  7997. returns FALSE, the coercion handler expects a pointer to the data.
  7998.  
  7999. The isSysHandler parameter specifies the coercion table from which to get the
  8000. handler. If its value is TRUE, the handler is taken from the system coercion
  8001. table. If its value is FALSE, the handler is taken from the application coercion
  8002. table.
  8003.  
  8004.    Result codes
  8005.           noErr                                                0      No error
  8006.           memFullErr                             –108      Not enough room in
  8007.           heap zone
  8008.           errAEHandlerNotFound    –1717      No handler found for an Apple event
  8009.           or 
  8010.                                                                              a
  8011.  
  8012.  
  8013.  
  8014. The AERemoveCoercionHandler function removes a coercion handler routine from
  8015. either the application or system coercion table.
  8016.  
  8017. FUNCTION AERemoveCoercionHandler (fromType: DescType; toType: DescType; 
  8018.                                   handler: ProcPtr; isSysHandler: 
  8019.                                   Boolean) : OSErr;
  8020.  
  8021. The fromType parameter is the descriptor type of the data coerced by the
  8022. handler.
  8023.  
  8024. The toType parameter is the descriptor type of the resulting data.
  8025.  
  8026. The handler parameter is a pointer to the coercion handler routine. Although the
  8027. fromType and toType parameters would be sufficient to identify the handler to be
  8028. removed, providing the handler parameter is a safeguard to ensure that you
  8029. remove the correct handler.
  8030.  
  8031. The isSysHandler parameter specifies the coercion table from which to remove the
  8032. handler. If its value is TRUE, the handler is removed from the system coercion
  8033. table. If its value is FALSE, the handler is removed from the application
  8034. coercion table.
  8035.  
  8036.    Result codes
  8037.           noErr                                                0      No error
  8038.           memFullErr                             –108      Not enough room in
  8039.           heap zone
  8040.           errAEHandlerNotFound    –1717      No handler found for an Apple event
  8041.           or 
  8042.                                                                              a
  8043.  
  8044.  
  8045. _______________________________________________________________________________
  8046.  
  8047. æKY Creating…and…Managing…the…Special…Handler…Tables
  8048. æC »Creating and Managing the Special Handler Tables               The Apple Event Manager
  8049. _______________________________________________________________________________
  8050.  
  8051. The AEInstallSpecialHandler function installs a handler in a special handler
  8052. table.
  8053.  
  8054. FUNCTION AEInstallSpecialHandler (functionClass: AEKeyword; handler: 
  8055.                                   ProcPtr; isSystemHandler: Boolean) : 
  8056.                                   OSErr;
  8057.  
  8058. The functionClass parameter is the keyword for the special handler that’s
  8059. installed. There is currently only one value allowed for this parameter: the
  8060. keyPreDispatch constant, which identifies a handler routine that is called
  8061. immediately before the Apple Event Manager dispatches an Apple event. If there
  8062. was already an entry in the specified special handler table for the same value
  8063. of functionClass, it is replaced.
  8064.  
  8065. The handler parameter is a pointer to the special handler. Note that a handler
  8066. in the system handler table must reside in the system heap; this means that if
  8067. the value of the isSysHandler parameter is TRUE, the handler parameter must
  8068. point to a location in the system heap.
  8069.  
  8070. The isSystemHandler parameter specifies the special handler table to which to
  8071. add the handler. If its value is TRUE, the handler is added to the system
  8072. handler table and made available to all applications. If its value is FALSE, the
  8073. handler is added to the application handler table.
  8074.  
  8075. If you put your handler code in the system heap or in your own heap, use the
  8076. AERemoveSpecialHandler function to remove the handler when your application
  8077. quits.
  8078.  
  8079.    Note:  When an application calls a system Apple event handler, the A5
  8080.    register is
  8081.    set up for the calling application. For this reason, if you provide a system
  8082.    Apple 
  8083.    event handler, it should never use A5 global variables or anything that
  8084.    depends 
  8085.    on a particular context; otherwise, the application that calls the system
  8086.    handler 
  8087.    may crash.
  8088.  
  8089.    Result codes
  8090.           noErr                                                    0      No
  8091.           error
  8092.           paramErr                                         –50      Parameter
  8093.           error (handler pointer is 
  8094.                                                                                
  8095.                                                                                
  8096.                                                                                
  8097.  
  8098.           memFullErr                                  –108      Not enough room
  8099.           in heap zone
  8100.           errAENotASpecialFunction    –1714      Wrong keyword for a special
  8101.           function
  8102.  
  8103. The AEGetSpecialHandler function returns a specified special handler.
  8104.  
  8105. FUNCTION AEGetSpecialHandler (functionClass: AEKeyword; VAR handler: 
  8106.                               ProcPtr; isSystemHandler: Boolean) : 
  8107.                               OSErr;
  8108.  
  8109. The functionClass parameter is the keyword that specifies the desired special
  8110. handler. There is currently only one value allowed for this parameter: the
  8111. keyPreDispatch constant, which identifies a handler routine that is called
  8112. immediately before the Apple Event Manager dispatches an Apple event.
  8113.  
  8114. The function returns a pointer to the special handler in the handler parameter.
  8115.  
  8116. The isSystemHandler parameter specifies the special handler table from which to
  8117. get the handler. If its value is TRUE, the handler is taken from the system
  8118. handler table. If its value is FALSE, the handler is taken from the application
  8119. handler table.
  8120.  
  8121.    Result codes
  8122.           noErr                                                    0      No
  8123.           error
  8124.           memFullErr                                  –108      Not enough room
  8125.           in heap zone
  8126.           errAENotASpecialFunction    –1714      Wrong keyword for a special
  8127.           function
  8128.  
  8129. The AERemoveSpecialHandler function removes a handler from a special handler
  8130. table.
  8131.  
  8132. FUNCTION AERemoveSpecialHandler (functionClass: AEKeyword; handler: ProcPtr; 
  8133.                                  isSystemHandler: Boolean) : OSErr;
  8134.  
  8135. The functionClass parameter is the keyword for the special handler to be
  8136. removed. There is currently only one value allowed for the functionClass
  8137. parameter: the keyPreDispatch constant, which identifies a handler routine that
  8138. is called immediately before the Apple Event Manager dispatches an Apple event.
  8139.  
  8140. The handler parameter is a pointer to the special handler to be removed.
  8141. Although the functionClass parameter would be sufficient to identify the handler
  8142. to be removed, providing the handler parameter is a safeguard to ensure that you
  8143. remove the correct handler.
  8144.  
  8145. The isSystemHandler parameter specifies the special handler table from which to
  8146. remove the handler. If its value is TRUE, the handler is taken from the system
  8147. handler table. If its value is FALSE, the handler is removed from the
  8148. application handler table.
  8149.  
  8150.    Result codes
  8151.           noErr                                                    0       No
  8152.           error
  8153.           memFullErr                                  –108      Not enough room
  8154.           in heap zone
  8155.           errAENotASpecialFunction    –1714      Wrong keyword for a special
  8156.           function
  8157. _______________________________________________________________________________
  8158.  
  8159. æKY Summary…of…the…Apple…Events…Manager…Volume…VI
  8160. æC »Summary of the Apple Events Manager Volume VI                  The Apple Event Manager
  8161. _______________________________________________________________________________
  8162.  
  8163. Click the arrow in the lower-right corner of this window to see the summary
  8164. sections of the constants, data types, and routines for the Apple Event Manager.
  8165.  
  8166.  
  8167.  
  8168. _______________________________________________________________________________
  8169.  
  8170. æKY Apple…Events…Manager…Constants
  8171. æC »Apple Events Manager Constants                                 The Apple Event Manager
  8172. _______________________________________________________________________________
  8173.  
  8174. CONST  gestaltAppleEventsAttr  = 'evnt';     {selector for Apple events}
  8175.        gestaltAppleEventsPresent
  8176.                                = 0;          {if set, Apple Event }
  8177.                                              { Manager is available}
  8178.  
  8179.        {Apple event descriptor types}
  8180.        typeBoolean             = 'bool';     {Boolean value}
  8181.        typeChar                = 'TEXT';     {unterminated string}
  8182.        typeSMInt               = 'shor';     {16-bit integer}
  8183.        typeInteger             = 'long';     {32-bit integer}
  8184.        typeSMFloat             = 'sing';     {SANE Single}
  8185.        typeFloat               = 'doub';     {SANE Double}
  8186.        typeLongInteger         = 'long';     {32-bit integer}
  8187.        typeShortInteger        = 'shor';     {16-bit integer}
  8188.        typeLongFloat           = 'doub';     {SANE Double}
  8189.        typeShortFloat          = 'sing';     {SANE Single}
  8190.        typeExtended            = 'exte';     {SANE Extended}
  8191.        typeComp                = 'comp';     {SANE Comp}
  8192.        typeMagnitude           = 'magn';     {unsigned 32-bit integer}
  8193.        typeAEList              = 'list';     {list of descriptor records}
  8194.        typeAERecord            = 'reco';     {list of keyword-specified }
  8195.                                              { descriptor records}
  8196.        typeAppleEvent          = 'aevt'      {Apple event record}
  8197.        typeTrue                = 'true';     {TRUE Boolean value}
  8198.        typeFalse               = 'fals';     {FALSE Boolean value}
  8199.        typeAlias               = 'alis';     {alias record}
  8200.        typeEnumerated          = 'enum';     {enumerated data}
  8201.        typeType                = 'type';     {descriptor type}
  8202.        typeAppParameters       = 'appa';     {Process Manager launch }
  8203.                                              { parameters}
  8204.        typeProperty            = 'prop';     {Apple event property}
  8205.        typeFSS                 = 'fss ';     {file system specification}
  8206.        typeKeyword             = 'keyw';     {Apple event keyword}
  8207.        typeSectionH            = 'sect';     {Edition Manager section }
  8208.                                              { handle}
  8209.        typeTemporaryID         = 'tid '      {temporary ID}
  8210.        typeWildCard            = '****';     {matches any type}
  8211.        typeApplSignature       = 'sign';     {application signature}
  8212.        typeSessionID           = 'ssid';     {session ID}
  8213.        typeTargetID            = 'targ';     {target ID}
  8214.        typeProcessSerialNumber
  8215.                                = 'psn ';     {process serial number}
  8216.        typeNull                = 'null';     {NULL or nonexistent data}
  8217.  
  8218.        {keywords for Apple event parameters}
  8219.        keyDirectObject         = '----';     {direct parameter}
  8220.        keyErrorNumber          = 'errn';     {error number parameter}
  8221.        keyErrorString          = 'errs';     {error string parameter}
  8222.        keyProcessSerialNumber  = 'psn ';     {process serial number param}
  8223.  
  8224.        {keywords for Apple event attributes}
  8225.        keyTransactionIDAttr    = 'tran';     {transaction ID}
  8226.        keyReturnIDAttr         = 'rtid';     {return ID}
  8227.        keyEventClassAttr       = 'evcl';     {event class}
  8228.        keyEventIDAttr          = 'evid';     {event ID}
  8229.        keyAddressAttr          = 'addr';     {target application}
  8230.        keyOptionalKeywordAttr  = 'optk';     {list of optional }
  8231.                                              { parameters for the }
  8232.                                              { Apple event}
  8233.        keyTimeoutAttr          = 'timo';     {number of ticks the client }
  8234.         { will wait}
  8235.        keyInteractLevelAttr    = 'inte';     {settings to allow Apple }
  8236.                                              { Event Mgr to bring }
  8237.                                              { server to foreground}
  8238.        keyEventSourceAttr      = 'esrc';     {source application}
  8239.        keyMissedKeywordAttr    = 'miss';     {first required parameter }
  8240.                                              { remaining in an Apple }
  8241.                                              { event}
  8242.  
  8243.        {keywords for special handlers}
  8244.        keyPreDispatch          = 'phac';     {identifies a handler }
  8245.                                              { routine that is called }
  8246.                                              { immediately before the }
  8247.                                              { Apple Event Manager }
  8248.                                              { dispatches an Apple event}
  8249.  
  8250.        {event classes}
  8251.        kCoreEventClass         = 'aevt';     {event class for core }
  8252.                                              { Apple events}
  8253.  
  8254.        {event IDs}
  8255.        kAEApplicationDied       = 'obit'     {event ID for Application }
  8256.                                              { Died event}
  8257.        kAEOpenApplication       = 'oapp';    {event ID for Open }
  8258.                                              { Application event}
  8259.        kAEOpenDocuments         = 'odoc';    {event ID for Open }
  8260.                                              { Documents event}
  8261.        kAEPrintDocuments        = 'pdoc';    {event ID for Print }
  8262.                                              { Documents event}
  8263.        kAEQuitApplication       = 'quit';    {event ID for Quit }
  8264.                                              { Application event}
  8265.        kAEAnswer                = 'ansr';    {event ID for Apple event }
  8266.                                              { replies}
  8267.  
  8268.        {constants for setting the sendMode parameter of AESend and for }
  8269.        { the keyInteractLevelAttr attribute}
  8270.        kAENoReply               = $00000001; {client doesn't want a reply}
  8271.        kAEQueueReply            = $00000002; {client wants server to }
  8272.                                              { reply in event queue}
  8273.        kAEWaitReply             = $00000003; {client wants a reply and }
  8274.                                              { will give up processor}
  8275.        kAENeverInteract         = $00000010; {server application should }
  8276.                                              { not interact with user }
  8277.                                              { for this Apple event}
  8278.        kAECanInteract           = $00000020; {server may interact with }
  8279.                                              { user for this Apple }
  8280.                                              { to supply information}
  8281.                                              { event}
  8282.        kAEAlwaysInteract        = $00000030; {server may interact with }
  8283.                                              { user for this Apple event }
  8284.                                              { even if no information }
  8285.                                              { is required}
  8286.        kAECanSwitchLayer        = $00000040; {server should come }
  8287.                                              { directly to foreground }
  8288.                                              { when appropriate}
  8289.        kAEDontReconnect         = $00000080; {don't reconnect if there }
  8290.                                              { is a PPC sessClosedErr}
  8291.        kAEWantReceipt           = nReturnReceipt;
  8292.                                              {client wants return receipt}
  8293.  
  8294.        {constants for the sendPriority parameter of AESend}
  8295.        kAENormalPriority        = $00000000; {put event at the back of }
  8296.                                              { event queue}
  8297.        kAEHighPriority          = nAttnMsg;  {put event at the front of }
  8298.                                              { the event queue}
  8299.  
  8300.        {constant for the returnID parameter of AECreateAppleEvent}
  8301.        kAutoGenerateReturnID    = -1;        {tells Apple Event Manager }
  8302.                                              { to generate a unique }
  8303.                                              { return ID}
  8304.  
  8305.        {constant for transaction IDs}
  8306.        kAnyTransactionID        = 0;         {the Apple event is not }
  8307.                                              { part of a transaction}
  8308.  
  8309.        {constants for timeout durations}
  8310.        kAEDefaultTimeout        = -1;        {use default timeout value}
  8311.        kNoTimeOut               = -2;        {never time out}
  8312.  
  8313.        {constants for the dispatcher parameter of AEResumeTheCurrentEvent}
  8314.        kAENoDispatch            = 0;         {don't redispatch the }
  8315.                                              { Apple event}
  8316.        kAEUseStandardDispatch   = -1;        {redispatch the Apple event }
  8317.                                              { by using its entry in the }
  8318.                                              { Apple event dispatch table}
  8319.           
  8320. _______________________________________________________________________________
  8321.  
  8322. æKY Apple…Events…Manager…Data…Types
  8323. æC »Apple Events Manager Data Types                                The Apple Event Manager
  8324. _______________________________________________________________________________
  8325.  
  8326. TYPE
  8327.      AEEventClass = 
  8328.         PACKED ARRAY[1..4] OF Char;           {event class for a }
  8329.                                               { high-level event}
  8330.      AEEventID = 
  8331.         PACKED ARRAY[1..4] OF Char;           {event ID for a high-level }
  8332.                                               { event}
  8333.      DescType                  = ResType;     {descriptor type}
  8334.  
  8335.      AEDesc = 
  8336.      RECORD                                   {descriptor record}
  8337.          descriptorType:       DescType;      {type of data being passed}
  8338.          dataHandle:           Handle          {handle to data being passed}
  8339.      END;
  8340.  
  8341.      AEKeyword = 
  8342.        PACKED ARRAY[1..4] OF Char;             {keyword for a descriptor}
  8343.  
  8344.      AEKeyDesc =                               {keyword-specified }
  8345.                                                { descriptor record}
  8346.      RECORD
  8347.         descKey:               AEKeyword;      {keyword}
  8348.         descContent:           AEDesc;         {descriptor record}
  8349.      END;
  8350.  
  8351.      AEAddressDesc             = AEDesc;       {descriptor containing an }
  8352.                                                { Apple event address}
  8353.  
  8354.      AEDescList                = AEDesc;       {list of descriptor records}
  8355.  
  8356.      AERecord                  = AEDescList;   {list of keyword-specified }
  8357.                                                { descriptor records}
  8358.  
  8359.      AppleEvent                = AERecord;     {list of attributes and }
  8360.                                                { parameters necessary for }
  8361.                                                { an Apple event}
  8362.      AESendMode                = LongInt;      {flags that determine how }
  8363.                                                { an Apple event is sent}
  8364.  
  8365.      AESendPriority            = Integer;      {send priority of an Apple }
  8366.                                                { event}
  8367.  
  8368.      AEInteractAllowed = (kAEInteractWithSelf, kAEInteractWithLocal,
  8369.                           kAEInteractWithAll);
  8370.                                               {what processes may }
  8371.                                               { interact with the user}
  8372.  
  8373.      AEEventSource = (kAEUnknownSource, kAEDirectCall, kAESameProcess,
  8374.                       kAELocalProcess, kAERemoteProcess);
  8375.                                               {the source of an Apple }
  8376.                                               { event; the type of the }
  8377.                                               { keyEventSourceAttr }
  8378.                                               { attribute}
  8379.  
  8380.      AEArrayType = (kAEDataArray, kAEPackedArray, kAEHandleArray, 
  8381.                     kAEDescArray, kAEKeyDescArray);
  8382.                                               {type of an Apple event }
  8383.                                               { array}
  8384.  
  8385.      AEArrayData = 
  8386.      RECORD                                   {data for an Apple event }
  8387.                                               { array}
  8388.          case AEArrayType OF
  8389.          kAEDataArray:
  8390.          (AEDataArray:      ARRAY[0..0] OF Integer);
  8391.          kAEPackedArray:  
  8392.          (AEPackedArray:    PACKED ARRAY[0..0] OF Char);
  8393.          kAEHandleArray:  
  8394.          (AEHandleArray:    ARRAY[0..0] OF Handle);
  8395.          kAEDescArray:  
  8396.          (AEDescArray:      ARRAY[0..0] OF AEDesc);
  8397.          kAEKeyDescArray:  
  8398.          (AEKeyDescArray:   ARRAY[0..0] OF AEKeyDesc);
  8399.      END;
  8400.   
  8401.      AEArrayDataPointer = ^AEArrayData;
  8402.  
  8403.      EventHandlerProcPtr = ProcPtr;           {pointer to an Apple event }
  8404.                                               { handler routine}
  8405.  
  8406.      IdleProcPtr = ProcPtr;                   {pointer to an app's }
  8407.                                               { idle function}
  8408.  
  8409.      EventFilterProcPtr = ProcPtr;            {pointer to an app's filter }
  8410.                                               { procedure}
  8411. _______________________________________________________________________________
  8412.  
  8413. æKY Apple…Events…Manager…Routines…Summary
  8414. æC »Apple Events Manager Routines Summary                          The Apple Event Manager
  8415. _______________________________________________________________________________
  8416.  
  8417. Creating and Managing the Apple Event Dispatch Tables
  8418.  
  8419. FUNCTION AEInstallEventHandler  (theAEEventClass: AEEventClass;
  8420.                                  theAEEventID: AEEventID; handler:
  8421.                                  EventHandlerProcPtr; handlerRefcon:
  8422.                                  LongInt; isSysHandler: Boolean) : OSErr;
  8423.  
  8424. FUNCTION AEGetEventHandler      (theAEEventClass: AEEventClass; theAEEventID:
  8425.                                  AEEventID; VAR handler: EventHandlerProcPtr;
  8426.                                  VAR handlerRefcon: LongInt; isSysHandler:
  8427.                                  Boolean) : OSErr;
  8428.  
  8429. FUNCTION AERemoveEventHandler   (theAEEventClass: AEEventClass; theAEEventID:
  8430.                                  AEEventID; handler: EventHandlerProcPtr;
  8431.                                  isSysHandler: Boolean) : OSErr;
  8432.  
  8433.  
  8434. Dispatching Apple Events
  8435.  
  8436. FUNCTION AEProcessAppleEvent  (theEventRecord: EventRecord) : OSErr;
  8437.  
  8438.  
  8439. Getting Parameters and Attributes From Apple Events
  8440.  
  8441. FUNCTION AEGetParamPtr        (theAppleEvent: AppleEvent; theAEKeyword:
  8442.                                AEKeyword; desiredType: DescType;
  8443.                                VAR typeCode: DescType; dataPtr: Ptr;
  8444.                                maximumSize: Size; VAR actualSize: Size) : 
  8445.                                OSErr;
  8446.  
  8447. FUNCTION AEGetParamDesc      (theAppleEvent: AppleEvent; theAEKeyword: 
  8448.                               AEKeyword; desiredType: DescType; VAR result:
  8449.                               AEDesc) : OSErr;
  8450.  
  8451. FUNCTION AEGetAttributePtr   (theAppleEvent: AppleEvent; theAEKeyword: 
  8452.                               AEKeyword; desiredType: DescType; VAR typeCode:
  8453.                               DescType; dataPtr: Ptr; maximumSize: Size;
  8454.                               VAR actualSize: Size) : OSErr;
  8455.  
  8456. FUNCTION AEGetAttributeDesc  (theAppleEvent: AppleEvent; theAEKeyword: 
  8457.                               AEKeyword; desiredType: DescType; VAR result: 
  8458.                               AEDesc) : OSErr;
  8459.  
  8460. Counting the Items in Descriptor Lists
  8461.  
  8462. FUNCTION AECountItems        (theAEDescList: AEDescList; VAR theCount: 
  8463.                               LongInt) : OSErr;
  8464.  
  8465. Getting Items From Descriptor Lists
  8466.  
  8467. FUNCTION AEGetNthPtr         (theAEDescList: AEDescList; index: LongInt; 
  8468.                               desiredType: DescType; VAR theAEKeyword: 
  8469.                               AEKeyword; VAR typeCode: DescType; dataPtr:
  8470.                               Ptr; maximumSize: Size; VAR actualSize: Size) 
  8471.                               : OSErr;
  8472.  
  8473. FUNCTION AEGetNthDesc       (theAEDescList: AEDescList; index: LongInt;
  8474.                              desiredType: DescType; VAR theAEKeyword:
  8475.                              AEKeyword; VAR result: AEDesc) : OSErr;
  8476.  
  8477. FUNCTION AEGetArray         (theAEDescList: AEDescList; arrayType: 
  8478.                              AEArrayType; arrayPtr: AEArrayDataPointer; 
  8479.                              maximumSize: Size; VAR itemType: DescType; VAR 
  8480.                              itemSize: Size; VAR itemCount: LongInt) : OSErr;
  8481.  
  8482. Getting Data and Keyword-Specified Descriptor Records From AE Records
  8483.  
  8484. FUNCTION AEGetKeyPtr         (theAERecord: AERecord; theAEKeyword: AEKeyword;
  8485.                               desiredType: DescType; VAR typeCode: DescType; 
  8486.                               dataPtr: Ptr; maximumSize: Size;
  8487.                               VAR actualSize: Size) : OSErr;
  8488.  
  8489. FUNCTION AEGetKeyDesc        (theAERecord: AERecord; theAEKeyword: AEKeyword;
  8490.                               desiredType: DescType; VAR result: AEDesc) 
  8491.                               : OSErr;
  8492.  
  8493.  
  8494. Requesting User Interaction
  8495.  
  8496. FUNCTION AESetInteractionAllowed  (level: AEInteractAllowed) : OSErr;
  8497.  
  8498. FUNCTION AEInteractWithUser       (timeOutInTicks: LongInt; nmReqPtr: 
  8499.                                    QElemPtr; idleProc: IdleProcPtr) : OSErr;
  8500.  
  8501. FUNCTION AEGetInteractionAllowed  (VAR level: AEInteractAllowed) : OSErr;
  8502.  
  8503.  
  8504. Requesting More Time to Respond to Apple Events
  8505.  
  8506. FUNCTION AEResetTimer   (reply: AppleEvent) : OSErr;
  8507.  
  8508.  
  8509. Suspending and Resuming Apple Event Handling
  8510.  
  8511. FUNCTION AESuspendTheCurrentEvent  (theAppleEvent: AppleEvent) : OSErr;
  8512.  
  8513. FUNCTION AEResumeTheCurrentEvent   (theAppleEvent, reply: AppleEvent; 
  8514.                                     dispatcher: EventHandlerProcPtr; 
  8515.                                     handlerRefcon: LongInt) : OSErr;
  8516.  
  8517. FUNCTION AESetTheCurrentEvent      (theAppleEvent: AppleEvent) : OSErr;
  8518.  
  8519. FUNCTION AEGetTheCurrentEvent      (VAR theAppleEvent: AppleEvent): OSErr;
  8520.    
  8521.  
  8522. Creating Apple Events
  8523.  
  8524. FUNCTION AECreateAppleEvent        (theAEEventClass: AEEventClass; 
  8525.                                     theAEEventID: AEEventID; target: 
  8526.                                     AEAddressDesc; returnID: Integer; 
  8527.                                     transactionID: LongInt; VAR result: 
  8528.                                     AppleEvent) : OSErr;
  8529.  
  8530.  
  8531. Creating and Duplicating Descriptor Records
  8532.  
  8533. FUNCTION AECreateDesc          (typeCode: DescType; dataPtr: Ptr; dataSize: 
  8534.                                 Size; VAR result: AEDesc) : OSErr;
  8535.  
  8536. FUNCTION AEDuplicateDesc       (theAEDesc: AEDesc; VAR result: AEDesc)
  8537.                                 : OSErr;
  8538.  
  8539.  
  8540. Creating Descriptor Lists and AE Records
  8541.  
  8542. FUNCTION AECreateList          (factoringPtr: Ptr; factoredSize: Size; 
  8543.                                 isRecord: Boolean; VAR resultList: 
  8544.                                 AEDescList) : OSErr;
  8545.  
  8546.  
  8547. Adding Items to Descriptor Lists
  8548.  
  8549. FUNCTION AEPutPtr              (theAEDescList: AEDescList; index: LongInt; 
  8550.                                 typeCode: DescType; dataPtr: Ptr; dataSize: 
  8551.                                 Size) : OSErr;
  8552.  
  8553. FUNCTION AEPutDesc             (theAEDescList: AEDescList; index: LongInt; 
  8554.                                 theAEDesc: AEDesc) : OSErr;
  8555.  
  8556. FUNCTION AEPutArray            (theAEDescList: AEDescList; arrayType: 
  8557.                                 AEArrayType; arrayPtr: AEArrayDataPointer; 
  8558.                                 itemType: DescType; itemSize: Size; 
  8559.                                 itemCount: LongInt) : OSErr;
  8560.  
  8561.  
  8562. Adding Keyword-Specified Descriptor Records to AE Records
  8563.  
  8564. FUNCTION AEPutKeyPtr           (theAERecord: AERecord; theAEKeyword: 
  8565.                                 AEKeyword; typeCode: DescType; dataPtr: Ptr; 
  8566.                                 dataSize: Size) : OSErr;
  8567.  
  8568. FUNCTION AEPutKeyDesc          (theAERecord: AERecord; theAEKeyword: 
  8569.                                 AEKeyword; theAEDesc: AEDesc) : OSErr;
  8570.  
  8571.  
  8572. Adding Parameters and Attributes to Apple Events
  8573.  
  8574. FUNCTION AEPutParamPtr         (theAppleEvent: AppleEvent; theAEKeyword: 
  8575.                                 AEKeyword; typeCode: DescType; dataPtr: Ptr; 
  8576.                                 dataSize: Size) : OSErr;
  8577.  
  8578. FUNCTION AEPutParamDesc        (theAppleEvent: AppleEvent; theAEKeyword: 
  8579.                                 AEKeyword; theAEDesc: AEDesc) : OSErr;
  8580.  
  8581. FUNCTION AEPutAttributePtr     (theAppleEvent: AppleEvent; theAEKeyword:
  8582.                                 AEKeyword; typeCode: DescType; dataPtr: Ptr; 
  8583.                                 dataSize: Size) : OSErr;
  8584.  
  8585. FUNCTION AEPutAttributeDesc    (theAppleEvent: AppleEvent; theAEKeyword: 
  8586.                                 AEKeyword; theAEDesc: AEDesc) : OSErr;
  8587.  
  8588.  
  8589. Sending Apple Events
  8590.  
  8591. FUNCTION AESend                (theAppleEvent: AppleEvent; VAR reply: 
  8592.                                 AppleEvent; sendMode: AESendMode; 
  8593.                                 sendPriority: AESendPriority; timeOutInTicks: 
  8594.                                 LongInt; idleProc: IdleProcPtr; filterProc: 
  8595.                                 EventFilterProcPtr) : OSErr;
  8596.  
  8597.  
  8598. Getting the Sizes and Descriptor Types of Descriptor Records
  8599.  
  8600. FUNCTION AESizeOfNthItem      (theAEDescList: AEDescList; index: LongInt; VAR
  8601.                                typeCode: DescType; VAR dataSize: Size)
  8602.                                : OSErr;
  8603.  
  8604. FUNCTION AESizeOfKeyDesc      (theAERecord: AERecord; theAEKeyword: 
  8605.                                AEKeyword; VAR typeCode: DescType;
  8606.                                VAR dataSize: Size) : OSErr;
  8607.  
  8608. FUNCTION AESizeOfParam        (theAppleEvent: AppleEvent; theAEKeyword: 
  8609.                                AEKeyword; VAR typeCode: DescType;
  8610.                                VAR dataSize: Size) : OSErr;
  8611.  
  8612. FUNCTION AESizeOfAttribute    (theAppleEvent: AppleEvent; theAEKeyword: 
  8613.                                AEKeyword; VAR typeCode: DescType;
  8614.                                VAR dataSize: Size) : OSErr;
  8615.  
  8616.  
  8617. Deleting Descriptor Records
  8618.  
  8619. FUNCTION AEDeleteItem         (theAEDescList: AEDescList; index: LongInt)
  8620.                                : OSErr;
  8621.  
  8622. FUNCTION AEDeleteKeyDesc      (theAERecord: AERecord; theAEKeyword: 
  8623.                                AEKeyword) : OSErr;
  8624.  
  8625. FUNCTION AEDeleteParam        (theAppleEvent: AppleEvent; theAEKeyword: 
  8626.                                AEKeyword) : OSErr;
  8627.  
  8628.  
  8629. Deallocating Memory for Descriptor Records
  8630.  
  8631. FUNCTION AEDisposeDesc        (VAR theAEDesc: AEDesc) : OSErr;
  8632.  
  8633.  
  8634. Coercing Descriptor Types
  8635.  
  8636. FUNCTION AECoercePtr          (typeCode: DescType; dataPtr: Ptr; dataSize: 
  8637.                                Size; toType: DescType; VAR result: AEDesc)
  8638.                                : OSErr;
  8639.  
  8640. FUNCTION AECoerceDesc        (theAEDesc: AEDesc; toType: DescType;
  8641.                               VAR result: AEDesc) : OSErr;
  8642.  
  8643.  
  8644. Creating and Managing the Coercion Handler Tables
  8645.  
  8646. FUNCTION AEInstallCoercionHandler  (fromType: DescType; toType: DescType;
  8647.                                     handler: ProcPtr; handlerRefcon: LongInt;
  8648.                                     fromTypeIsDesc: Boolean; isSysHandler: 
  8649.                                     Boolean) : OSErr;
  8650.  
  8651. FUNCTION AEGetCoercionHandler      (fromType: DescType; toType: DescType;
  8652.                                     VAR handler: ProcPtr; VAR handlerRefcon: 
  8653.                                     LongInt; VAR fromTypeIsDesc: Boolean; 
  8654.                                     isSysHandler: Boolean) : OSErr;
  8655.  
  8656. FUNCTION AERemoveCoercionHandler   (fromType: DescType; toType: DescType; 
  8657.                                     handler: ProcPtr; isSysHandler: Boolean) 
  8658.                                     : OSErr;
  8659.  
  8660.  
  8661. Creating and Managing the Special Handler Tables
  8662.  
  8663. FUNCTION AEInstallSpecialHandler   (functionClass: AEKeyword; handler: 
  8664.                                     ProcPtr; isSystemHandler: Boolean)
  8665.                                     : OSErr;
  8666.  
  8667. FUNCTION AEGetSpecialHandler       (functionClass: AEKeyword; VAR handler:
  8668.                                     ProcPtr; isSystemHandler: Boolean)
  8669.                                     : OSErr;
  8670.  
  8671. FUNCTION AERemoveSpecialHandler    (functionClass: AEKeyword; handler: 
  8672.                                     ProcPtr; isSystemHandler: Boolean)
  8673.                                     : OSErr;
  8674.  
  8675.  
  8676. Application-Defined Routines
  8677.  
  8678. FUNCTION MyEventHandler         (theAppleEvent: AppleEvent; reply: 
  8679.                                  AppleEvent; handlerRefcon: LongInt) : OSErr; 
  8680.  
  8681. FUNCTION MyCoercePtr            (typeCode: DescType; dataPtr: Ptr; dataSize: 
  8682.                                  Size; toType: DescType; handlerRefcon: 
  8683.                                  LongInt; VAR result: AEDesc) : OSErr; 
  8684.  
  8685. FUNCTION MyCoerceDesc           (theAEDesc: AEDesc; toType: DescType; 
  8686.                                  handlerRefcon: LongInt; VAR result: AEDesc) 
  8687.                                  : OSErr;
  8688.  
  8689. FUNCTION MyIdleFunction         (VAR theEventRecord: EventRecord;
  8690.                                  VAR sleepTime: LongInt; VAR mouseRgn: 
  8691.                                  RgnHandle) : Boolean;
  8692.  
  8693. FUNCTION MyWaitReplyFilter      (VAR theEventRecord: EventRecord; 
  8694.                                  transactionID: LongInt; returnID: LongInt; 
  8695.                                  sender: AEAddressDesc) : Boolean;
  8696. _______________________________________________________________________________
  8697.  
  8698. æKY Apple…Events…Manager…Result…Codes
  8699. æC »Apple Events Manager Result Codes                              The Apple Event Manager
  8700. _______________________________________________________________________________
  8701.  
  8702. noErr                                                      0     No error
  8703. paramErr                                           –50     Parameter error
  8704. (handler pointer is NIL or 
  8705.                                                                         odd)
  8706. memFullErr                                    –108     Not enough room in heap
  8707. zone
  8708. bufferIsSmall                                  –607     Buffer is too small
  8709. noOutstandingHLE                       –608     No outstanding high-level event
  8710. connectionInvalid                         –609     Connection is invalid
  8711. errAECoercionFail                       –1700     Data could not be coerced to
  8712. the requested
  8713.  
  8714.                                                                          type
  8715. errAEDescNotFound                   –1701     Descriptor record was not found
  8716. errAECorruptData                        –1702     Data in an Apple event could
  8717. not be read
  8718. errAEWrongDataType                –1703     Wrong descriptor type
  8719. errAENotAEDesc                         –1704      Not a valid descriptor record
  8720. errAEBadListItem                        –1705     Operation involving a list
  8721. item failed
  8722. errAENewerVersion                   –1706     Need a newer version of the Apple
  8723. Event 
  8724.                                                                          Manager
  8725. errAENotAppleEvent                 –1707     Event is not an Apple event
  8726. errAEEventNotHandled            –1708     Event wasn’t handled by an Apple event
  8727.  
  8728.                                                                          handler
  8729. errAEReplyNotValid                  –1709     AEResetTimer was passed an invalid
  8730. reply
  8731. errAEUnknownSendMode       –1710     Invalid sending mode was passed
  8732. errAEWaitCanceled                    –1711     User canceled out of wait loop
  8733. for reply or 
  8734.                                                                          receipt
  8735. errAETimeout                              –1712     Apple event timed out
  8736. errAENoUserInteraction           –1713     No user interaction allowed
  8737. errAENotASpecialFunction     –1714     Wrong keyword for a special function
  8738. errAEParamMissed                     –1715     Handler did not get all required
  8739. parameters
  8740. errAEUnknownAddressType  –1716     Unknown Apple event address type
  8741. errAEHandlerNotFound           –1717     No handler found for an Apple event or
  8742.                                                                         coercion
  8743. errAEReplyNotArrived             –1718     Reply has not yet arrived
  8744. errAEIllegalIndex                        –1719     Not a valid list index
  8745. _______________________________________________________________________________
  8746.  
  8747. æKY Apple…Events…Manager…Assembly-Language…Information
  8748. æC »Apple Events Manager Assembly-Language Information             The Apple Event Manager
  8749. _______________________________________________________________________________
  8750.  
  8751. Trap Macros Requiring Routine Selectors
  8752.  
  8753. _Pack8
  8754.  
  8755.  
  8756. Selector           Routine
  8757.  
  8758.   $00                  AEInstallSpecialHandler
  8759.   $01                  AERemoveSpecialHandler
  8760.   $02                  AECoercePtr
  8761.   $03                  AECoerceDesc
  8762.   $04                  AEDisposeDesc
  8763.   $05                  AEDuplicateDesc
  8764.   $06                  AECreateList
  8765.   $07                  AECountItems
  8766.   $08                  AEPutPtr
  8767.   $09                  AEPutDesc
  8768.   $0A                 AEGetNthPtr
  8769.   $0B                 AEGetNthDesc
  8770.   $0C                 AEGetArray
  8771.   $0D                AEPutArray
  8772.   $0E                 AEDeleteItem
  8773.   $0F                 AEPutKeyPtr
  8774.   $0F                 AEPutParamPtr
  8775.   $10                 AEPutKeyDesc
  8776.   $10                 AEPutParamDesc
  8777.   $11                 AEGetParamPtr
  8778.   $11                 AEGetKeyPtr
  8779.   $12                 AEGetKeyDesc
  8780.   $12                 AEGetParamDesc
  8781.   $13                 AEDeleteKeyDesc
  8782.   $13                 AEDeleteParam
  8783.   $14                 AECreateAppleEvent
  8784.   $15                 AEGetAttributePtr
  8785.   $16                 AEPutAttributePtr
  8786.   $17                 AESend
  8787.   $18                 AEResumeTheCurrentEvent
  8788.   $19                 AEResetTimer
  8789.   $1A                AEGetTheCurrentEvent
  8790.   $1B                 AEProcessAppleEvent
  8791.   $1C                 AEInteractWithUser
  8792.   $1D                 AEGetInteractionAllowed
  8793.   $1E                 AESetInteractionAllowed
  8794.   $1F                 AEInstallEventHandler
  8795.   $20                 AERemoveEventHandler
  8796.   $21                 AEGetEventHandler
  8797.   $22                 AEInstallCoercionHandler
  8798.   $23                 AERemoveCoercionHandler
  8799.   $24                 AEGetCoercionHandler 
  8800.   $25                 AECreateDesc
  8801.   $26                 AEGetAttributeDesc
  8802.   $27                 AEPutAttributeDesc
  8803.   $28                 AESizeOfAttribute
  8804.   $29                 AESizeOfParam
  8805.   $29                 AESizeOfKeyDesc
  8806.   $2A                AESizeOfNthItem
  8807.   $2B                 AESuspendTheCurrentEvent
  8808.   $2C                 AESetTheCurrentEvent
  8809.   $2D                 AEGetSpecialHandler
  8810.  
  8811.  
  8812. _______________________________________________________________________________
  8813.  
  8814.  
  8815. æKY AppleTalkManager
  8816. æC 
  8817. _______________________________________________________________________________
  8818.  
  8819. APPLETALK MANAGER
  8820. _______________________________________________________________________________
  8821.  
  8822. About…Appletalk…Manager…Chapter…Volume…VI
  8823. About…the…Appletalk…Manager…Volume…VI
  8824.     Changes…to…the…Appletalk…Manager
  8825.     Appletalk…Protocols
  8826.     Device…Drivers,connection…Files,…&…the…LAP…Manager
  8827. Using…the…Appletalk…Manager…Volume…VI
  8828.     Determining…if…Appletalk…Phase…2…Drivers…Are…Present
  8829.     Deciding…Which…Appletalk…Protocol…to…Use
  8830. The….MPP…Driver…Volume…VI
  8831.     Getting…Information…About…the….MPP…Driver
  8832.     A…New…Nbp…Wildcard…Character
  8833. The…LAP…Manager…Volume…VI
  8834.     The…Appletalk…Transition…Queue
  8835.         Adding…and…Removing…Appletalk…Transition…Queue…Entries
  8836.         Sending…Messages…to…the…Appletalk…Transition…Queue
  8837.         How…the…Appletalk…Manager…Calls…Your…Queue…Entry
  8838.         Defining…Your…Own…Appletalk…Transition
  8839.     The…LAP…Manager…802.2…Protocol
  8840.     Attaching…and…Detaching…802.2…Protocol…Handlers
  8841. The….ATP…Driver…Volume…VI
  8842.     Canceling…All…Calls…to…the…Atpgetrequest…Function
  8843.     Setting…the…Timeout…Value…for…the…Atp…Release…Timer
  8844. The….XPP…Driver…Volume…VI
  8845.     Using…the….XPP…Driver…to…Obtain…Information…About…Zones
  8846.     Obtaining…Zone…Information
  8847. Appletalk…Data…Stream…Protocol…(adsp)…Volume…VI
  8848.     Using…ADSP
  8849.         The…ADSP…Connection…Control…Block
  8850.         The….DSP…Parameter…Block
  8851.         Opening…and…Maintaining…an…ADSP…Connection
  8852.         Creating…and…Using…a…Connection…Listener
  8853.         Writing…a…User…Routine…for…Connection…Events
  8854.     .DSP…Driver…Routines
  8855.         Establishing…&…Terminating…an…ADSP…Connection
  8856.         Establishing…&…Terminating…an…ADSP…Connection…(cont'd)
  8857.         Establishing…&…Terminating…an…ADSP…Connection…Listener
  8858.         Maintaining…an…ADSP…Connection
  8859. The….ENET…Driver…Volume…VI
  8860.     Providing…Your…Own…Ethernet…Driver
  8861.     Changing…the…Ethernet…Hardware…Address
  8862.     Opening…the….ENET…Driver
  8863.     Using…a…Write-Data…Structure…to…Transmit…Ethernet…Data
  8864.     Using…the…Default…Ethernet…Protocol…Handler…to…Read…Data
  8865.     Using…Your…Own…Ethernet…Protocol…Handler…to…Read…Data
  8866.         How…the….ENET…Driver…Calls…Your…Protocol…Handler
  8867.         How…Your…Protocol…Handler…Calls…the….ENET…Driver
  8868.     .ENET…Driver…Routines
  8869.         Attaching…and…Detaching…an…Ethernet…Protocol…Handler
  8870.         Writing…and…Reading…Ethernet…Packets
  8871.         Adding…and…Removing…Ethernet…Multicast…Addresses
  8872. Summary…of…the…Appletalk…Manager…Volume…VI
  8873.     Appletalk…Manager…Constants
  8874.     Appletalk…Manager…Data…Types
  8875.     Appletalk…Manager…Routines…Summary
  8876.     Appletalk…Manager…Global…Variable
  8877.     Appletalk…Manager…Result…Codes
  8878.     Appletalk…Manager…Assembly-language…Information
  8879.     
  8880. About…The…AppleTalkManager…Chapter
  8881. AppleTalk…Protocols
  8882. AppleTalk…Transaction…Protocol
  8883. About…the…AppleTalk…Manager
  8884. Calling…the…AppleTalk…Manager…from…Pascal
  8885. New…AppleTalk…Manager…Pascal…Interface
  8886. Picking…a…Node…Address…in…the…Server…Range
  8887. Sending…Packets…to…One’s…Own…Node
  8888. ATP…Driver…Changes
  8889. Name…Binding…Protocol…Changes
  8890. Variable…Resources
  8891. Calling…the…AppleTalk…Manager…from…Assembly…Language
  8892. Extended…Protocol…Package…Driver
  8893. Calling…the….XPP…Driver
  8894. Protocol…Handlers…and…Socket…Listeners
  8895. Summary…of…the…AppleTalk…Manager
  8896.  
  8897. _______________________________________________________________________________
  8898.  
  8899.  
  8900.  
  8901. æKY About…Appletalk…Manager…Chapter…Volume…VI
  8902. æC »About Appletalk Manager Chapter Volume VI                            AppleTalk Manager
  8903. _______________________________________________________________________________
  8904.  
  8905. AppleTalk® is a communications network system including personal computer
  8906. workstations, computers acting as file servers and print servers, printers, and
  8907. a variety of types of communications hardware and software. The AppleTalk
  8908. Manager provides an interface to this communications network system for
  8909. applications running on Macintosh® computers. This chapter describes changes to
  8910. the AppleTalk Manager introduced since the publication of Inside Macintosh ,
  8911. Volume V, and included with system software version 7.0. This chapter
  8912. supplements the information in the AppleTalk Manager chapters of Inside
  8913. Macintosh, Volumes II and V.
  8914.  
  8915. This chapter describes 
  8916.  
  8917.   •  new routines for the .MPP, .ATP, and .XPP device drivers
  8918.  
  8919.   •  a new wildcard character for use with the Name-Binding Protocol
  8920.  
  8921.   •  a new operating-system queue, called the AppleTalk Transition Queue
  8922.  
  8923.   •  a new set of operating-system utilities, collectively called the LAP
  8924.   Manager
  8925.  
  8926.   •  the application interface routines provided by a new AppleTalk protocol,
  8927.   the
  8928.       AppleTalk Data Stream Protocol (ADSP)
  8929.  
  8930.   •  the .ENET driver and the routines your application can use to control this
  8931.       driver
  8932.  
  8933. Together with the AppleTalk Manager chapters of Volumes II and V, this chapter
  8934. describes the routines that your application can use to send and receive
  8935. information within an AppleTalk network system. Because the AppleTalk network
  8936. system includes both hardware and software—and because the software includes not
  8937. only the AppleTalk Manager but also file servers, print servers, internet
  8938. routers, drivers for circuit cards, and so forth—the information in Inside
  8939. Macintosh  constitutes only a small part of the body of literature documenting
  8940. AppleTalk.
  8941.  
  8942. For a detailed description of AppleTalk protocols, see Inside AppleTalk . For a
  8943. complete description of the LAP Manager, EtherTalk®, and alternate AppleTalk
  8944. connections, see the AppleTalk Connections Programmer’s Guide . To learn how to
  8945. install and operate an AppleTalk internet, see the AppleTalk Internet Router
  8946. Administrator’s Guide  and the AppleTalk Phase 2 Introduction and Upgrade Guide
  8947. . For an introduction to the hardware and software of an entire AppleTalk
  8948. network, see Understanding Computer Networks  and the AppleTalk Network System
  8949. Overview . For information on designing circuit cards and device drivers for
  8950. Macintosh computers, see Designing Cards and Drivers for the Macintosh Family .
  8951.  
  8952. The changes to AppleTalk other than ADSP and the LAP Manager are collectively
  8953. referred to as AppleTalk Phase 2. (When necessary for purposes of
  8954. differentiation, the previous version of AppleTalk is referred to in this
  8955. chapter as AppleTalk Phase 1.) The Phase 2 versions of the AppleTalk drivers are
  8956. included as part of system software version 7.0 and can be installed on any
  8957. Macintosh computer other than the Macintosh 128K, Macintosh 512K, Macintosh 512K
  8958. enhanced, and Macintosh XL computers. If you want to provide AppleTalk Phase 2
  8959. drivers with your product, you must obtain a license from Apple® Software
  8960. Licensing.
  8961.  
  8962. _______________________________________________________________________________
  8963.  
  8964. æKY About…the…Appletalk…Manager…Volume…VI
  8965. æC »About the Appletalk Manager Volume VI                                AppleTalk Manager
  8966. _______________________________________________________________________________
  8967.  
  8968. The AppleTalk Manager includes a number of protocols that are implemented in
  8969. various device drivers. The AppleTalk Manager also includes the LAP Manager
  8970. (which interfaces the AppleTalk link access protocols to the higher-level
  8971. AppleTalk protocols), and hardware device drivers for specific data links.
  8972. Software that supports AppleTalk data links is contained in files of type
  8973. 'adev', referred to as AppleTalk connection files . This section lists the new
  8974. features of AppleTalk, describes the organization of the AppleTalk Manager, and
  8975. briefly discusses what each component of the AppleTalk Manager does. 
  8976.  
  8977. _______________________________________________________________________________
  8978.  
  8979. æKY Changes…to…the…Appletalk…Manager
  8980. æC »Changes to the Appletalk Manager                                     AppleTalk Manager
  8981. _______________________________________________________________________________
  8982.  
  8983. The AppleTalk features that are new or improved include
  8984.  
  8985.   •  a new .MPP driver function that returns information about the .MPP driver
  8986.       (see “Getting Information About the .MPP Driver,” later in this chapter)
  8987.  
  8988.   •  a new Name-Binding Protocol (NBP) wildcard character that can substitute
  8989.   for
  8990.       one or more characters in AppleTalk names (see “A New NBP Wildcard
  8991.       Character”)
  8992.  
  8993.   •  the LAP Manager, a set of operating-system utilities that provide a
  8994.   standard
  8995.       interface between the AppleTalk protocols and the data links used by
  8996.       AppleTalk, such as LocalTalk®, EtherTalk, and TokenTalk® (see “The LAP
  8997.       Manager”)
  8998.  
  8999.   •  the AppleTalk Transition Queue, an operating-system queue that can notify
  9000.       your application each time an AppleTalk driver is opened or closed or each
  9001.       time certain other transitions occur (see “The AppleTalk Transition
  9002.       Queue”)
  9003.  
  9004.   •  an implementation of parts of the IEEE 802.2 protocol, which allows you to
  9005.       attach and detach your own protocol handlers for EtherTalk data packets
  9006.       (see
  9007.       “The LAP Manager 802.2 Protocol”)
  9008.  
  9009.   •  new .ATP driver functions that allow you to set a value for the .ATP
  9010.   release
  9011.       timer and to cancel all pending asynchronous calls to the the
  9012.       ATPGetRequest
  9013.       function for a specific socket (see “The .ATP Driver”)
  9014.  
  9015.   •  new .XPP driver functions that provide information from ZIP about zones
  9016.   (see
  9017.       “The .XPP Driver”)
  9018.  
  9019.   •  improvements to the AppleTalk protocols that allow a single network, other
  9020.       than LocalTalk, to contain more than one zone (see “Using the .XPP Driver
  9021.       to
  9022.       Obtain Zone Information”)
  9023.  
  9024.   •  the AppleTalk Data Stream Protocol (ADSP), which provides full-duplex data
  9025.       stream communications for use by applications (see “AppleTalk Data Stream
  9026.       Protocol”)
  9027.  
  9028.   •  the .ENET driver, an Ethernet driver for the EtherTalk NB card that is
  9029.       manufactured by Apple Computer, Inc. (see “The .ENET Driver”)
  9030. _______________________________________________________________________________
  9031.  
  9032. æKY Appletalk…Protocols
  9033. æC »Appletalk Protocols                                                  AppleTalk Manager
  9034. _______________________________________________________________________________
  9035.  
  9036. The AppleTalk Manager includes the following protocols:
  9037.  
  9038.   •  LocalTalk Link Access Protocol (LLAP)
  9039.  
  9040.   •  EtherTalk Link Access Protocol (ELAP)
  9041.  
  9042.   •  TokenTalk Link Access Protocol (TLAP)
  9043.  
  9044.   •  Datagram Delivery Protocol (DDP)
  9045.  
  9046.   •  Routing Table Maintenance Protocol (RTMP)
  9047.  
  9048.   •  AppleTalk Transaction Protocol (ATP)
  9049.  
  9050.   •  Name-Binding Protocol (NBP)
  9051.  
  9052.   •  AppleTalk Echo Protocol (AEP)
  9053.  
  9054.   •  Zone Information Protocol (ZIP)
  9055.  
  9056.   •  AppleTalk Session Protocol (ASP)
  9057.  
  9058.   •  AppleTalk Data Stream Protocol (ADSP)
  9059.  
  9060.   •  AppleTalk Filing Protocol (AFP)
  9061.  
  9062. The LocalTalk Link Access Protocol, EtherTalk Link Access Protocol, TokenTalk
  9063. Link Access Protocol, and other link access protocols provide interfaces between
  9064. the AppleTalk Manager and the different types of data link hardware used by
  9065. AppleTalk.
  9066.  
  9067.    Note:  The LocalTalk Link Access Protocol (LLAP) was originally called the
  9068.    AppleTalk Link Access Protocol (ALAP). With the addition of the EtherTalk
  9069.    Link
  9070.    Access Protocol (ELAP) and other link access protocols, this protocol was
  9071.    renamed
  9072.    to indicate the specific data link it supports.
  9073.  
  9074. Figure 32-1 shows the relationships among the various AppleTalk protocols. A
  9075. line going from a protocol to another protocol above or below it in the figure
  9076. indicates that the upper protocol is a client of the lower protocol; that is,
  9077. the upper protocol uses services provided by the lower protocol in order to
  9078. carry out some functions.
  9079.  
  9080. ¿ Figure 32-1   AppleTalk protocols ø 
  9081.  
  9082.    Note:  The various AppleTalk protocols are sets of rules, not computer
  9083.    programs,
  9084.    and so can be implemented in many different ways on many different systems.
  9085.    All of the AppleTalk protocol functions that you can address or control from
  9086.    a
  9087.    Macintosh application are implemented as Macintosh device drivers or
  9088.    managers. Many other features of these protocols are implemented in software
  9089.    located only on internet routers that are not used to run general
  9090.    applications.
  9091.    Some parts of protocols are implemented by server software such as file
  9092.    servers
  9093.    and print servers. Therefore, when this chapter refers to a protocol as
  9094.    “doing” or
  9095.    “controlling” something, you should understand the statement to mean that
  9096.    some program that implements the protocol actually carries out the operation.
  9097.  
  9098. As shown in Figure 32-1, a link access protocol controls the access of the node
  9099. to the network hardware and makes it possible for many nodes to share the same
  9100. communications hardware. Each link access protocol assigns a node ID to the node
  9101. and decodes the node addresses of messages it receives. A link access protocol
  9102. provides node-to-node delivery of data packets. Examples of link access
  9103. protocols include the LocalTalk Link Access Protocol, the EtherTalk Link Access
  9104. Protocol, and the TokenTalk Link Access Protocol. 
  9105.  
  9106. Whereas earlier implementations of AppleTalk were restricted to one 16-bit
  9107. network number per network (that is, one network number for all nodes connected
  9108. with no intervening routers) and 254 nodes per network number, AppleTalk Phase 2
  9109. allows more than one network number for each network (other than LocalTalk,
  9110. which is still limited to one network number per network). A network of a type
  9111. that allows more than one network number is known as an extended network. Each
  9112. node in an extended network must now be specified by both its 16-bit network
  9113. number and its 8-bit node ID. In principle, each network (other than LocalTalk)
  9114. can now have over 16 million  (224) nodes. In any specific implementation, the
  9115. hardware or software might limit the network to fewer nodes.
  9116.  
  9117. The Datagram Delivery Protocol (DDP) provides socket-to-socket delivery of data
  9118. packets within an AppleTalk internet. The address of a DDP packet includes the
  9119. socket number, node ID, and network number. Application interface routines for
  9120. DDP are described in “Datagram Delivery Protocol” in the AppleTalk Manager
  9121. chapter of Volume II.
  9122.  
  9123. The Routing Table Maintenance Protocol (RTMP) is used by routers on an AppleTalk
  9124. internet to determine how to forward a data packet to the network number to
  9125. which it is addressed. The RTMP implementation on a router maintains a table,
  9126. called a routing table, that specifies the shortest path to each possible
  9127. destination network number. The AppleTalk protocol software in a workstation
  9128. (that is, a node other than a router) contains only a small part of RTMP, called
  9129. the RTMP stub, that DDP uses to determine the network number (or range of
  9130. network numbers) of the network cable to which the node is connected and to
  9131. determine the network number and node ID of one router on that network cable.
  9132. There is no application interface to the RTMP stub.
  9133.  
  9134. The AppleTalk Transaction Protocol (ATP) provides reliable delivery of data by
  9135. retransmitting any data packets that are lost. ATP also ensures that data
  9136. packets are delivered in the correct sequence. ATP is a transaction-based
  9137. protocol, meaning that one socket client transmits a request for some action and
  9138. the other socket client carries out the action and transmits a response.
  9139. Although—as you can see from Figure 32-1—the AppleTalk Manager provides
  9140. high-level protocols that are clients of ATP, many applications use ATP directly
  9141. to transmit data over an AppleTalk internet. The application interface to ATP is
  9142. described in the AppleTalk Manager chapter of Volume II. There are some
  9143. enhancements to ATP in AppleTalk Phase 2, described in “The .ATP Driver” later
  9144. in this chapter.
  9145.  
  9146. The Name-Binding Protocol (NBP) maintains a table that contains the internet
  9147. address and name of each entity in the node that is visible to other entities on
  9148. the internet (that is, each entity that has registered a name with NBP). The
  9149. internet address includes the socket number, node ID, and network number. The
  9150. name consists of three fields: the object, type, and zone. The object and type
  9151. are assigned by the entity itself and can be anything the user or application
  9152. assigns. A zone is a logical grouping of a subset of the nodes on the internet.
  9153. The zone field of the name is the zone in which the node resides.
  9154.  
  9155. NBP also allows its clients to obtain the internet address of any
  9156. network-visible entity in the internet by providing its name. NBP maps this name
  9157. to an internet address, thus providing the link between the user-supplied name
  9158. for an entity and the internet address that is used by DDP to send and receive
  9159. data packets. The application interface to NBP is described in the AppleTalk
  9160. Manager chapter of Volume II. There is one enhancement to NBP in AppleTalk Phase
  9161. 2, described in “A New NBP Wildcard Character” later in this chapter.
  9162.  
  9163. The AppleTalk Echo Protocol (AEP) listens for special packets sent by other
  9164. nodes and, when it receives such a packet, echoes it back to the sender. AEP is
  9165. used by some clients of DDP to determine whether another node (known to have
  9166. AEP) can be accessed over the internet, and to determine how long it takes a
  9167. packet to reach another node. There is no application interface to AEP.
  9168.  
  9169. The Zone Information Protocol (ZIP) maintains a table in each router, called the
  9170. zone information table, that lists the relationships between zone names and
  9171. networks. In AppleTalk Phase 2, a single network number can be associated with
  9172. more than one zone name, or a single zone name can be associated with more than
  9173. one network. You can use .XPP driver routines to obtain information from ZIP.
  9174. These routines are discussed in “Using the .XPP Driver to Obtain Information
  9175. About Zones” later in this chapter.
  9176.  
  9177. The AppleTalk Session Protocol (ASP) sets up and maintains sessions between a
  9178. workstation and a server. A session consists of a logical (as opposed to
  9179. physical) connection between two entities on the internet. ASP is a
  9180. nonsymmetrical protocol; that is, only one of the two entities involved in the
  9181. session (the workstation) can send commands. The other entity (the server) is
  9182. restricted to responding to the commands. ASP is used by the AppleTalk Filing
  9183. Protocol, for example, to allow a user to manipulate files on a file server. As
  9184. long as the session is open, the workstation can request directory information,
  9185. change filenames, and so forth. The file server must respond to the
  9186. workstation’s commands and cannot initiate any actions on its own. ASP is
  9187. discussed in the AppleTalk Manager chapter of Volume V.
  9188.  
  9189. The AppleTalk Data Stream Protocol (ADSP) appears to its clients to maintain an
  9190. open pipeline between two entities on the internet. Either entity can write a
  9191. stream of bytes to the pipeline or read data bytes from the pipeline. ADSP is a
  9192. symmetrical protocol; that is, the two clients at either end of the connection
  9193. are equal and can perform exactly the same operations. ADSP is especially useful
  9194. for exchanging information between two equal entities, as in a telephone
  9195. communications network, or as required by a terminal emulation program for
  9196. sending or receiving a continuous stream of data. Because ADSP, like all other
  9197. high-level AppleTalk protocols is a client of DDP, the data is actually sent as
  9198. data packets. This allows ADSP to correct transmission errors in a way that
  9199. would not be possible for a true data stream connection. Thus, ADSP retains many
  9200. of the advantages of a transaction-based protocol while providing to its clients
  9201. a full-duplex data stream. ADSP is discussed in the sections “Using ADSP” and
  9202. “.DSP Driver Routines” later in this chapter.
  9203.  
  9204. The AppleTalk Filing Protocol (AFP) provides an interface between an application
  9205. and a file server. AFP is a client of ASP and is used to access AppleShare® file
  9206. servers on Macintosh computer workstations. When the user opens a session with
  9207. an AppleShare file server over an internet, it appears to any application
  9208. running on the workstation that uses File Manager routines as if the files on
  9209. the file server were located on a disk drive connected to the workstation. The
  9210. application interface to AFP is described in the AppleTalk Manager chapter of
  9211. Volume V. 
  9212.  
  9213. _______________________________________________________________________________
  9214.  
  9215. æKY Device…Drivers,connection…Files,…&…the…LAP…Manager
  9216. æC »Device Drivers,connection Files, & the LAP Manager                   AppleTalk Manager
  9217. _______________________________________________________________________________
  9218.  
  9219. A protocol is only a set of rules, not a computer program. The various AppleTalk
  9220. protocols are implemented as Macintosh device drivers, including
  9221.  
  9222.   •  the .MPP driver, which implements LLAP, DDP, the RTMP stub, NBP, and AEP
  9223.  
  9224.   •  the .ATP driver, which implements ATP
  9225.  
  9226.   •  the .XPP driver, which implements ASP and the workstation portions of ZIP
  9227.       and AFP
  9228.  
  9229.   •  the .DSP driver, which implements ADSP
  9230.  
  9231.   •  the .ENET driver, which implements an interface to the Ethernet data link
  9232.  
  9233. A Macintosh computer on an AppleTalk network can also include one or more
  9234. AppleTalk connection files. An AppleTalk connection file has file type 'adev'
  9235. and contains a link access protocol implementation for a data link (ELAP for
  9236. EtherTalk, for example). The LAP Manager makes it possible for the user to
  9237. select among AppleTalk connection files by using the Network control panel to
  9238. specify which network is to be used for the node’s AppleTalk connection. The
  9239. AppleTalk connection file and LAP Manager work together with the Network control
  9240. panel (Network 'cdev') file. When the user selects a connection from the Network
  9241. control panel, the LAP Manager routes AppleTalk communications through the
  9242. selected link access protocol and hence through the selected hardware.
  9243.  
  9244. The AppleTalk device drivers, LAP Manager, and AppleTalk connection files are
  9245. shown in Figure 32-2. As you can see from the figure, each device driver
  9246. implements one or more AppleTalk protocols.
  9247.  
  9248. ¿ Figure 32-2   AppleTalk device drivers ø 
  9249.  
  9250. Figure 32-3 shows the interfaces between a general application on a Macintosh
  9251. computer being used as an AppleTalk workstation and the AppleTalk protocols, the
  9252. LAP Manager, and the Ethernet hardware device driver. The lines connecting the
  9253. application to the various components of AppleTalk indicate which components
  9254. have application interfaces. As discussed in the preceding section, “AppleTalk
  9255. Protocols,” each application interface is described, at least in part, in this
  9256. or another volume of Inside Macintosh . 
  9257.  
  9258. ¿ Figure 32-3   AppleTalk application interfaces ø 
  9259.  
  9260.  
  9261. _______________________________________________________________________________
  9262.  
  9263. æKY Using…the…Appletalk…Manager…Volume…VI
  9264. æC »Using the Appletalk Manager Volume VI                                AppleTalk Manager
  9265. _______________________________________________________________________________
  9266.  
  9267. This section describes how to determine whether AppleTalk Phase 2 drivers are
  9268. present and gives some advice on how to select the AppleTalk protocol that best
  9269. serves your purposes. This section also describes how to use the features added
  9270. to AppleTalk with Phase 2 and provides programming examples of the use of the
  9271. .DSP driver and several other new AppleTalk features.
  9272.  
  9273. _______________________________________________________________________________
  9274.  
  9275. æKY Determining…if…Appletalk…Phase…2…Drivers…Are…Present
  9276. æC »Determining if Appletalk Phase 2 Drivers Are Present                 AppleTalk Manager
  9277. _______________________________________________________________________________
  9278.  
  9279. Once the .MPP driver has been loaded into memory, you can use the Gestalt
  9280. function with the gestaltAppleTalkVersion selector to check the version of
  9281. AppleTalk. The Gestalt function returns the version of the .MPP driver. If the
  9282. version is equal to or greater than 53, then the .MPP driver supports AppleTalk
  9283. Phase 2, and you can assume the other Phase 2 drivers are present.
  9284.  
  9285. Alternatively, you can call the SysEnvirons function as described in the
  9286. Compatibility Guidelines chapter of Volume V. If the atDrvrVersNum field of the
  9287. SysEnvRec data structure returned by this function is equal to or greater than
  9288. 53, then the .MPP driver supports AppleTalk Phase 2.
  9289.  
  9290. The ExtendedBit flag returned by the pGetAppleTalkInfo function is TRUE if the
  9291. node is connected to an extended AppleTalk network. (The ExtendedBit flag is bit
  9292. 15 of the configuration parameter returned by this function.) Note that the
  9293. presence of the AppleTalk Phase 2 drivers does not of itself indicate that the
  9294. node is connected to an extended network. 
  9295.  
  9296. _______________________________________________________________________________
  9297.  
  9298. æKY Deciding…Which…Appletalk…Protocol…to…Use
  9299. æC »Deciding Which Appletalk Protocol to Use                             AppleTalk Manager
  9300. _______________________________________________________________________________
  9301.  
  9302. AppleTalk offers a variety of communications protocols at a variety of levels.
  9303. Your choice of protocol or protocols to use depends primarily on your needs and
  9304. can be influenced by your familiarity with network communications in general. 
  9305.  
  9306. You can write your own protocol handlers and call the low-level AppleTalk device
  9307. drivers directly. However, if you are not a communications expert and have no
  9308. desire to design your own network protocols, you should probably use one of
  9309. three AppleTalk protocols for sending and receiving data over the AppleTalk
  9310. internet: the AppleTalk Transaction Protocol (ATP), the AppleTalk Session
  9311. Protocol (ASP), or the AppleTalk Data Stream Protocol (ADSP). 
  9312.  
  9313. ATP is a lower-level protocol than ASP or ADSP. You cannot use ATP to establish
  9314. a session and keep it open; rather, you request data from another socket client
  9315. or send a response (up to eight packets of data) from your socket to another
  9316. socket client that has requested data. You should use ATP if you want only to
  9317. send a small amount of data and do not need the overhead required to maintain an
  9318. open connection. ATP is described in the AppleTalk Manager chapters of Volume II
  9319. and Volume V.
  9320.  
  9321. ASP is designed to support a session between a server and one or more
  9322. workstations. It is an asymmetrical protocol: all exchanges are initiated by a
  9323. workstation and responded to by a server. The server cannot initiate an exchange
  9324. of data except to send to a workstation an attention message that directs the
  9325. workstation to request data from the server. An application running on a
  9326. workstation must make calls to ASP to communicate with any server that uses ASP.
  9327. If you want to develop a new type of asymmetrical, transaction-oriented server,
  9328. you should consider using ASP to implement it. ASP is described in the AppleTalk
  9329. Manager chapter of Volume V.
  9330.  
  9331. ADSP is a symmetrical protocol that you can use to establish and maintain a
  9332. connection between two equal entities (a peer-to-peer connection). Either end of
  9333. an ADSP connection can send data at any time. Although ADSP is a client of DDP
  9334. and therefore sends and receives data in packets (as do ATP and ASP), to an
  9335. application using ADSP the data appears to be sent and received as a continuous
  9336. stream. In addition to the duplex data stream maintained by an ADSP session,
  9337. ADSP allows either end of a connection to send an attention message to the other
  9338. end. You can use ADSP to establish two-way communication between computers, such
  9339. as an interoffice party line or a terminal emulation program. If you want to
  9340. develop an application that requires two-way communication, you should consider
  9341. using ADSP to implement it. ADSP is described in “Using ADSP” later in this
  9342. chapter.
  9343.  
  9344. _______________________________________________________________________________
  9345.  
  9346. æKY The….MPP…Driver…Volume…VI
  9347. æC »The .MPP Driver Volume VI                                            AppleTalk Manager
  9348. _______________________________________________________________________________
  9349.  
  9350. Within the AppleTalk Manager, the .MPP driver implements the LocalTalk Link
  9351. Access Protocol (LLAP), the Datagram Delivery Protocol (DDP), the Routing Table
  9352. Maintenance Protocol (RTMP) stub, the Name-Binding Protocol (NBP), and the
  9353. AppleTalk Echo Protocol (AEP). The AppleTalk Phase 2 version of the .MPP driver
  9354. includes a new function that returns information about the .MPP driver,
  9355. functions that send messages to routines in the AppleTalk Transition Queue, and
  9356. a new wildcard character for NBP.
  9357.  
  9358. _______________________________________________________________________________
  9359.  
  9360. æKY Getting…Information…About…the….MPP…Driver
  9361. æC »Getting Information About the .MPP Driver                            AppleTalk Manager
  9362. _______________________________________________________________________________
  9363.  
  9364. You can use the PGetAppleTalkInfo function to obtain information about the .MPP
  9365. driver. The PGetAppleTalkInfo function returns 
  9366.  
  9367.   •  a pointer to the .MPP global variables 
  9368.  
  9369.   •  a pointer to the .MPP driver’s device control entry (DCE) data structure
  9370.  
  9371.   •  configuration flags that indicate the status of certain conditions that are
  9372.   set at
  9373.       startup
  9374.  
  9375.   •  a value (the selfSend flag) that indicates whether the node can send
  9376.   packets to
  9377.       itself
  9378.  
  9379.   •  the range of network numbers for the network to which the node is attached
  9380.  
  9381.   •  the 8-bit node ID and 16-bit network number of the node
  9382.  
  9383.   •  the 8-bit node ID and 16-bit network number of the last router from which
  9384.   the 
  9385.        node has heard
  9386.  
  9387.   •  the maximum capacities of the .MPP driver, such as the maximum number of
  9388.       protocol handlers and the maximum number of static sockets allowed by this
  9389.       driver
  9390.  
  9391.   •  a pointer to the registered names queue
  9392.  
  9393.   •  the address of the node on the underlying data link (for example, the
  9394.   Ethernet
  9395.       hardware address)
  9396.  
  9397.   •  the node’s zone name
  9398.  
  9399. The data link address (for example, the Ethernet hardware address) and the zone
  9400. name are returned only for extended networks; that is, network types that allow
  9401. more than one network number per network. You must allocate memory for and
  9402. provide pointers to the data buffers into which the PGetAppleTalkInfo function
  9403. returns the data link address and zone name. You use the laLength parameter to
  9404. specify the length of the data link address you want returned; the function
  9405. returns the actual length of the data in the laLength parameter and returns the
  9406. data in the buffer you provide.
  9407.  
  9408.    Note:  Always use the PGetAppleTalkInfo function to obtain information about
  9409.    the .MPP driver. You can no longer rely on the validity of the global
  9410.    variables
  9411.    described in the AppleTalk Manager chapter of Volume II.
  9412.  
  9413. FUNCTION PGetAppleTalkInfo (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  9414.  
  9415. Parameter block
  9416.       ¨      16        ioResult             word          result code 
  9417.       Æ      26        csCode                word          always
  9418.       PGetAppleTalkInfo
  9419.       Æ      28        version              word          version of function
  9420.       ¨      30        varsPtr                long           pointer to .MPP
  9421.       globals
  9422.       ¨      34        dcePtr                  long           pointer to DCE for
  9423.       .MPP
  9424.       ¨      38        portID                 word          port number 
  9425.       ¨      40        configuration    long           configuration flags
  9426.       ¨      44        selfSend             word          nonzero if self-send
  9427.       is enabled
  9428.       ¨      46        netLo                  word          low value of the
  9429.       network range
  9430.       ¨      48        netHi                  word          high value of the
  9431.       network range
  9432.       ¨      50        ourAddr             long           local 24-bit AppleTalk
  9433.       address
  9434.       ¨      54        routerAddr        long           24-bit address of router
  9435.       ¨      58        numOfPHs        word          max number of protocol
  9436.       handlers
  9437.       ¨      60        numOfSkts        word          max number of static
  9438.       sockets
  9439.       ¨      62        numNBPEs       word          max concurrent NBP requests
  9440.       ¨      64        ntQueue              long          pointer to registered
  9441.       names queue
  9442.       ´      68        laLength             word          length in bytes of
  9443.       data link address
  9444.  
  9445.  
  9446.  
  9447.  
  9448.       Æ      70        linkAddr             long          pointer to data link
  9449.       address buffer
  9450.  
  9451.  
  9452.  
  9453.  
  9454.       Æ      74        zoneName          long          pointer to zone name
  9455.       buffer
  9456.  
  9457. The PGetAppleTalkInfo function returns information about the .MPP driver. If the
  9458. node on which your program is running happens also to be running AppleTalk
  9459. Internet Router software in the background, more than one set of .MPP global
  9460. variables may be in RAM. To make sure you are obtaining information about the
  9461. .MPP driver that handles application software, always use the PGetAppleTalkInfo
  9462. function rather than the Device Manager’s PBControl function. If you are using
  9463. assembly language or want to use the PBControl function, you must use a device
  9464. driver reference number of –10 for the .MPP driver.
  9465.  
  9466. Fields
  9467.  
  9468. ioResult                             The result of the function. When you
  9469. execute the function
  9470.                                              asynchronously, the function sets
  9471.                                              this parameter to 1 and
  9472.                                              returns a function result of noErr
  9473.                                              as soon as the function
  9474.                                              begins execution. When the function
  9475.                                              completes execution,
  9476.                                              it sets the ioResult parameter to
  9477.                                              the actual result code. 
  9478.  
  9479. csCode                                Routine selector, automatically set by the
  9480. MPW® interface.
  9481.                                             Always equal to PGetAppleTalkInfo
  9482.                                             for this function.
  9483.  
  9484. version                             The version number of the PGetAppleTalkInfo
  9485. function
  9486.                                             you are calling. For version number
  9487.                                             53 of the .MPP driver,
  9488.                                             this number is always 1.
  9489.  
  9490. varsPtr                              A pointer to the .MPP global variables.
  9491. This parameter is
  9492.                                             reserved for the use of Apple
  9493.                                             Computer, Inc.; you cannot
  9494.                                             rely on the validity of the
  9495.                                             variables pointed to by this
  9496.                                             parameter. 
  9497.  
  9498. dcePtr                                A pointer to the device control entry
  9499. (DCE) data structure
  9500.                                            for the .MPP driver. The DCE is
  9501.                                            described in the Device
  9502.                                            Manager chapters of Volumes II and V.
  9503.  
  9504. portID                               The port number for the .MPP driver. The
  9505. port number is
  9506.                                            always 0 unless you are requesting
  9507.                                            information for an .MPP
  9508.                                            driver being used by a router.
  9509.  
  9510. configuration                 A 32-bit long word of configuration flags. The
  9511. following
  9512.                                           flags are currently defined:
  9513.  
  9514.                                           Bit      Flag
  9515.                                           Description
  9516.                                           31       SrvAdrBit          TRUE (1)
  9517.                                           if the routine that opened
  9518.                                                                                
  9519.                                                                                
  9520.                                                                                
  9521.                                                                                
  9522.                                                                                
  9523.                                                                                
  9524.  
  9525.                                                                                
  9526.                                                                                
  9527.                                                                                
  9528.                                                                                
  9529.                                                                                
  9530.  
  9531.                                                                                
  9532.                                                                                
  9533.                                                                                
  9534.                                                                                
  9535.                                                                                
  9536.  
  9537.                                                                                
  9538.                                                                                
  9539.                                                                                
  9540.                                                                                
  9541.                                                                                
  9542.                                                                                
  9543.  
  9544.                                                                                
  9545.                                                                                
  9546.                                                                                
  9547.                                                                                
  9548.                                                                                
  9549.                                                                                
  9550.  
  9551.                                                                                
  9552.                                                                                
  9553.                                                                                
  9554.                                                                                
  9555.                                                                                
  9556.                                                                                
  9557.  
  9558.                                                                                
  9559.                                                                                
  9560.                                                                                
  9561.                                                                                
  9562.                                                                                
  9563.                                                                                
  9564.  
  9565.                                                                                
  9566.                                                                                
  9567.                                                                                
  9568.                                                                                
  9569.                                                                                
  9570.                                                                                
  9571.  
  9572.                                                                                
  9573.                                                                                
  9574.                                                                                
  9575.                                                                                
  9576.                                                                                
  9577.                                                                                
  9578.                                                                                
  9579.  
  9580.                                                                                
  9581.  
  9582.  
  9583.                                           30       RouterBit             TRUE
  9584.                                           (1) if an AppleTalk Internet
  9585.                                                                                
  9586.                                                                                
  9587.                                                                                
  9588.                                                                                
  9589.                                                                                
  9590.                                                                                
  9591.  
  9592.                                                                                
  9593.                                                                                
  9594.                                                                                
  9595.                                                                                
  9596.                                                                                
  9597.                                                                                
  9598.                                                                                
  9599.  
  9600.                                                                                
  9601.                                                                                
  9602.                                                                                
  9603.                                                                                
  9604.                                                                                
  9605.                                                                                
  9606.  
  9607.                                                                                
  9608.                                                                                
  9609.                                                                                
  9610.                                                                                
  9611.                                                                                
  9612.                                                                                
  9613.                                                                                
  9614.  
  9615.                                                                                
  9616.  
  9617.  
  9618.                                          15        ExtendedBit         TRUE (1)
  9619.                                          if the node is on an
  9620.                                                                                
  9621.                                                                                
  9622.                                                                                
  9623.                                                                                
  9624.                                                                                
  9625.                                                                                
  9626.  
  9627.                                                                                
  9628.                                                                                
  9629.                                                                                
  9630.                                                                                
  9631.                                                                                
  9632.                                                                                
  9633.  
  9634.                                                                                
  9635.                                                                                
  9636.                                                                                
  9637.                                                                                
  9638.                                                                                
  9639.                                                                                
  9640.  
  9641.  
  9642.                                            7       BadZoneHintBit   TRUE (1) if
  9643.                                            the zone name of the
  9644.                                                                                
  9645.                                                                                
  9646.                                                                                
  9647.                                                                                
  9648.                                                                                
  9649.                                                                                
  9650.                                                                                
  9651.                                                                                
  9652.                                                                                
  9653.  
  9654.                                                                                
  9655.                                                                                
  9656.                                                                                
  9657.                                                                                
  9658.                                                                                
  9659.                                                                                
  9660.  
  9661.                                                                                
  9662.                                                                                
  9663.                                                                                
  9664.                                                                                
  9665.                                                                                
  9666.                                                                                
  9667.  
  9668.                                                                                
  9669.                                                                                
  9670.                                                                                
  9671.                                                                                
  9672.                                                                                
  9673.                                                                                
  9674.  
  9675.                                                                                
  9676.                                                                                
  9677.                                                                                
  9678.                                                                                
  9679.                                                                                
  9680.                                                                                
  9681.                                                                                
  9682.  
  9683.                                                                                
  9684.                                                                                
  9685.                                                                                
  9686.                                                                                
  9687.                                                                                
  9688.                                                                                
  9689.  
  9690.                                                                                
  9691.                                                                                
  9692.                                                                                
  9693.                                                                                
  9694.                                                                                
  9695.                                                                                
  9696.  
  9697.                                                                                
  9698.                                                                                
  9699.                                                                                
  9700.                                                                                
  9701.                                                                                
  9702.                                                                                
  9703.  
  9704.                                                                                
  9705.                                                                                
  9706.                                                                                
  9707.                                                                                
  9708.  
  9709.                                                                                
  9710.  
  9711.  
  9712.                                            6       OneZoneBit           TRUE (1)
  9713.                                            if only one zone is
  9714.                                                                                
  9715.                                                                                
  9716.                                                                                
  9717.                                                                                
  9718.                                                                                
  9719.  
  9720.                                                                                
  9721.                                                                                
  9722.                                                                                
  9723.                                                                                
  9724.                                                                                
  9725.                                                                                
  9726.                                                                                
  9727.                                                                                
  9728.  
  9729.                                                                                
  9730.                                                                                
  9731.                                                                                
  9732.                                                                                
  9733.                                                                                
  9734.                                                                                
  9735.  
  9736.                                                                                
  9737.                                                                                
  9738.                                                                                
  9739.                                                                                
  9740.                                                                                
  9741.                                                                                
  9742.  
  9743.                                                                                
  9744.                                                                                
  9745.  
  9746.  
  9747. selfSend                           The ability of a node to send packets to
  9748. itself. This feature is
  9749.                                            enabled when this parameter is
  9750.                                            nonzero. Use the
  9751.                                            PSetSelfSend function, described in
  9752.                                            the AppleTalk Manager
  9753.                                            chapter of Volume V, to enable or
  9754.                                            disable this feature.
  9755.  
  9756. netLo                                 The low value of the range of network
  9757. numbers on the
  9758.                                             local cable. Only extended networks
  9759.                                             can have a range of
  9760.                                             network numbers. For a nonextended
  9761.                                             network, this
  9762.                                             parameter returns the network
  9763.                                             number.
  9764.  
  9765. netHi                                 The high value of the range of network
  9766. numbers on the
  9767.                                             local cable. Only extended networks
  9768.                                             can have a range of
  9769.                                             network numbers. For a nonextended
  9770.                                             network, this
  9771.                                             parameter returns the network
  9772.                                             number.
  9773.  
  9774. ourAddr                            The 24-bit AppleTalk network address of the
  9775. node you are
  9776.                                              on. The least significant byte of
  9777.                                              the long word is the node
  9778.                                              ID. The middle 16 bits are the
  9779.                                              network number. The most
  9780.                                              significant byte of the long word
  9781.                                              is reserved for use by
  9782.                                              Apple Computer, Inc. 
  9783.  
  9784. routerAddr                       The 24-bit AppleTalk network address of the
  9785. last router
  9786.                                              from which your node heard traffic.
  9787.                                              The least significant
  9788.                                              byte of the long word is the node
  9789.                                              ID. The middle 16 bits are
  9790.                                              the network number. The most
  9791.                                              significant byte of the long
  9792.                                              word is reserved for use by Apple
  9793.                                              Computer, Inc. You
  9794.                                              should always use this address when
  9795.                                              you want to
  9796.                                              communicate with a router.
  9797.  
  9798. numOfPHs                        The maximum number of protocol handlers that
  9799. this
  9800.                                              .MPP driver allows.
  9801.  
  9802. numOfSkts                        The maximum number of statically assigned
  9803. sockets that
  9804.                                               this .MPP driver allows.
  9805.                                               Statically assigned sockets are
  9806.                                               described in Inside AppleTalk.
  9807.  
  9808. numNBPEs                       The maximum number of concurrent requests to NBP
  9809. that
  9810.                                              this .MPP driver allows. 
  9811.  
  9812. ntQueue                             A pointer to the first entry in the names
  9813. table for the local
  9814.                                               node. You can use NBP routines to
  9815.                                               look up and register
  9816.                                               names in the names table. The
  9817.                                               names table is described in
  9818.                                              “Name-Binding Protocol” in the
  9819.                                              AppleTalk Manager
  9820.                                               chapter of Volume II.
  9821.  
  9822. laLength                            The number of bytes of the data link address
  9823. that the
  9824.                                              function should place in the buffer
  9825.                                              pointed to by the
  9826.                                              LinkAddr parameter. You use this
  9827.                                              parameter when you
  9828.                                              call the PGetAppleTalkInfo function
  9829.                                              on a node on an
  9830.                                              extended network. If you request
  9831.                                              more bytes than the total
  9832.                                              number of bytes in the address,
  9833.                                              then the function returns
  9834.                                              in the laLength parameter the
  9835.                                              actual number of bytes it
  9836.                                              placed in the buffer. If the
  9837.                                              address is longer than the size of
  9838.                                              the buffer, then the
  9839.                                              PGetAppleTalkInfo function fills
  9840.                                              the
  9841.                                              buffer and returns in the laLength
  9842.                                              parameter the actual
  9843.                                              length of the address, not the
  9844.                                              number of bytes returned. 
  9845.                                             The function does not return an
  9846.                                             error when the buffer is
  9847.                                              too large or too small for the
  9848.                                              address. A value of 6 bytes for
  9849.                                              laLength is sufficient for most
  9850.                                              purposes.
  9851.  
  9852. linkAddr                           A pointer to a buffer for the data link
  9853. address returned for
  9854.                                              extended networks only. You use the
  9855.                                              laLength parameter
  9856.                                              to specify the number of bytes of
  9857.                                              the address that you want
  9858.                                              placed in this buffer. You must
  9859.                                              allocate a buffer large
  9860.                                              enough to hold the number of bytes
  9861.                                              you specify. Specify
  9862.                                              NIL for this parameter if you do
  9863.                                              not want the function to
  9864.                                              provide a data link address.
  9865.  
  9866. zoneName                        A pointer to a buffer into which the
  9867. PGetAppleTalkInfo
  9868.                                              function places the local node’s
  9869.                                              zone name. You must
  9870.                                              allocate a buffer of at least 33
  9871.                                              bytes to hold this data, or you
  9872.                                             must specify NIL for the ZoneName
  9873.                                             parameter if you do
  9874.                                             not want to obtain the zone name.
  9875.                                             This field is returned
  9876.                                             only if the node is on an extended
  9877.                                             network.
  9878.    
  9879. Result codes
  9880.         noErr                     0           No error
  9881.         paramErr         –50            Version number is too high
  9882.  
  9883. _______________________________________________________________________________
  9884.  
  9885. æKY A…New…Nbp…Wildcard…Character
  9886. æC »A New Nbp Wildcard Character                                         AppleTalk Manager
  9887. _______________________________________________________________________________
  9888.  
  9889. The Name-Binding Protocol (NBP) allows the use of certain wildcard characters in
  9890. AppleTalk names when you call the PLookupName function. NBP now supports the
  9891. following wildcard characters:
  9892.  
  9893. NBP wildcard characters
  9894.  
  9895. =                                      All possible values. The equal sign (=)
  9896. can be used alone
  9897.                                          instead of a name in the object or type
  9898.                                          fields.
  9899.  
  9900. *                                      This zone. The asterisk (*) can be used
  9901. in place of the name of
  9902.                                         the zone to which this node belongs.
  9903.  
  9904. ≈                                      Any or no characters in this position.
  9905. The double tilde (≈) can
  9906.                                          be used to obtain matches for object or
  9907.                                          type fields. For
  9908.                                          example, pa≈l matches pal, paul, paper
  9909.                                          ball, and so forth. You
  9910.                                          can use only one double tilde in any
  9911.                                          string. Press Option-x to
  9912.                                         type the double tilde character on a
  9913.                                         Macintosh keyboard. If
  9914.                                         you use the double tilde alone, it has
  9915.                                         the same meaning as
  9916.                                         the equal sign (=). Note that any node
  9917.                                         not running AppleTalk
  9918.                                         Phase 2 drivers will not recognize this
  9919.                                         character.
  9920.  
  9921. _______________________________________________________________________________
  9922.  
  9923. æKY The…LAP…Manager…Volume…VI
  9924. æC »The LAP Manager Volume VI                                            AppleTalk Manager
  9925. _______________________________________________________________________________
  9926.  
  9927. The LAP Manager is a set of operating-system utilities that provide a standard
  9928. interface between the AppleTalk protocols and the various link access protocols,
  9929. such as LocalTalk (LLAP), EtherTalk (ELAP), and TokenTalk (TLAP). Because the
  9930. LAP Manager is running even when the .MPP driver is not open, the LAP Manager
  9931. also maintains the AppleTalk Transition Queue. In addition, the LAP Manager
  9932. contains protocol handlers for certain types of 802.2 packets. 
  9933.  
  9934. This section describes the AppleTalk Transition Queue and the LAP Manager 802.2
  9935. protocol handler, tells you how to add or remove an AppleTalk Transition Queue
  9936. entry, and describes how to attach or detach your own 802.2 protocol handler. In
  9937. addition to the LAP Manager features described here, you can use the LAP Manager
  9938. to interface new data links to AppleTalk. For more information about the LAP
  9939. Manager, see the AppleTalk Connections Programmer’s Guide . 
  9940.  
  9941. _______________________________________________________________________________
  9942.  
  9943. æKY The…Appletalk…Transition…Queue
  9944. æC »The Appletalk Transition Queue                                       AppleTalk Manager
  9945. _______________________________________________________________________________
  9946.  
  9947. At any given time there might be two or more applications running that use
  9948. AppleTalk. If one of these applications opens the AppleTalk drivers, the other
  9949. AppleTalk applications are affected. If the Operating System closes the
  9950. AppleTalk drivers, all AppleTalk applications are affected. To ensure that your
  9951. application is not adversely affected by such an event, your application can
  9952. place an entry in the AppleTalk Transition Queue. The LAP Manager sends a
  9953. message to each entry in the AppleTalk Transition Queue each time the Operating
  9954. System or any routine
  9955.  
  9956.   •  opens the .MPP driver
  9957.  
  9958.   •  closes the .MPP driver
  9959.  
  9960.   •  indicates that it intends to close the .MPP driver
  9961.  
  9962.   •  cancels its intention to close the .MPP driver
  9963.  
  9964.   •  defines its own AppleTalk event and calls the AppleTalk Transition Queue to
  9965.       inform it that such an event occurred
  9966.  
  9967. Each of these events is referred to as an AppleTalk transition.
  9968.  
  9969. Because the .MPP driver is not necessarily open when the AppleTalk Transition
  9970. Queue must be called, the LAP Manager maintains the queue. Each entry in the
  9971. AppleTalk Transition Queue is defined by the ATQentry data type.
  9972.  
  9973. TYPE ATQentry = 
  9974.      RECORD
  9975.         qLink:     ATQentryPtr;  {next queue entry}
  9976.         qType:     Integer;      {reserved}
  9977.         CallAddr:  ProcPtr       {pointer to your routine}
  9978.      END;
  9979.  
  9980. When you want to add an entry to the AppleTalk Transition Queue, you must create
  9981. an ATQentry data structure and give the LAP Manager a pointer to it. The qLink
  9982. field is a pointer to the next queue entry. You should set this field to NIL;
  9983. the LAP Manager fills it in when an application adds another entry to the queue.
  9984. The qType field is reserved to maintain consistency with other operating-system
  9985. queues. The CallAddr field is a pointer to a routine that you provide, as
  9986. described in “How the AppleTalk Manager Calls Your AppleTalk Transition Queue
  9987. Entry” later in this chapter.
  9988.  
  9989. Because you provide the memory for the AppleTalk Transition Queue entry, you can
  9990. add as many fields to the end of the entry as you wish for your own purposes.
  9991. Whenever your routine is called, the caller provides you with a pointer to the
  9992. queue entry so that you can have access to the information you stored at the end
  9993. of your queue entry.
  9994.  
  9995. There are four LAP Manager functions you can use that are related to the
  9996. AppleTalk Transition Queue:
  9997.  
  9998.   •  The LAPAddATQ function adds an entry to the AppleTalk Transition Queue.
  9999.       This function is described in the following section, “Adding and Removing
  10000.       AppleTalk Transition Queue Entries.”
  10001.  
  10002.   •  The LAPRmvATQ function removes an entry from the AppleTalk Transition
  10003.       Queue. This function is described in the following section, “Adding and
  10004.       Removing AppleTalk Transition Queue Entries.”
  10005.  
  10006.   •  The ATEvent procedure calls all the entries in the AppleTalk Transition
  10007.   Queue
  10008.       with an AppleTalk transition event of your own definition. This function
  10009.       is
  10010.       described in the section “Defining Your Own AppleTalk Transition,” later
  10011.       in
  10012.       this chapter.
  10013.  
  10014.   •  The ATPreFlightEvent function calls all the entries in the AppleTalk
  10015.       Transition Queue  with an AppleTalk transition event of your own
  10016.       definition
  10017.       and gives each entry the opportunity to respond. This function is
  10018.       described in
  10019.       the section “Defining Your Own AppleTalk Transition,” later in this
  10020.       chapter.
  10021.  
  10022. _______________________________________________________________________________
  10023.  
  10024. æKY Adding…and…Removing…Appletalk…Transition…Queue…Entries
  10025. æC »Adding and Removing Appletalk Transition Queue Entries               AppleTalk Manager
  10026. _______________________________________________________________________________
  10027.  
  10028. You can use LAP Manager routines to add or remove an entry to the AppleTalk
  10029. Transition Queue.
  10030.  
  10031.           _____________________________________________________
  10032.            Assembly-language note:  From assembly language, you add and 
  10033.            remove AppleTalk Transition Queue entries by placing a routine 
  10034.            selector in the D0 register, placing a pointer to your AppleTalk 
  10035.            Transition Queue entry in the A0 register, and executing a JSR 
  10036.            instruction to an offset past the start of the LAP Manager. The start
  10037.  
  10038.            of the LAP Manager is contained in the global variable LAPMgrPtr 
  10039.            ($B18). The offset to the LAP Manager routines is given by the 
  10040.            constant LAPMgrCall (2).
  10041.          
  10042.            Here is assembly-language code that adds or removes AppleTalk 
  10043.            Tranisition Queue entries:
  10044.  
  10045.            LAPMgrPtr        EQU     $B18          ;entry point for LAP Manager
  10046.       LAPMgrCall       EQU     2             ;offset to LAP Manager routines
  10047.       ATQEntry         EQU     *             ;pointer to ATQ entry
  10048.       ...    
  10049.  
  10050.                        MOVEQ   #RSel,D0      ;place routine selector 
  10051.                                              ; in D0 (23 to add an entry, 24
  10052.                                              ; to remove one)
  10053.                       MOVE.L  LAPMgrPtr,An   ;put pointer to LAP Mgr in An
  10054.                       MOVE.L  ATQEntry,A0    ;put ATQ entry in A0 
  10055.                       JSR     LAPMgrCall(An) ;jump to start of LAP Mgr
  10056.                                              ; routines
  10057.           _____________________________________________________
  10058.  
  10059. FUNCTION LAPAddATQ (theATQEntry: ATQEntryPtr): OSErr;
  10060.  
  10061.           __________________________________________________
  10062.            On entry                    D0: 23
  10063.                                                A0: pointer to AppleTalk
  10064.                                                Transition Queue entry
  10065.            On exit                       D0: result code
  10066.           __________________________________________________
  10067.  
  10068. The LAPAddATQ function adds an entry to the AppleTalk Transition Queue. The
  10069. parameter theATQEntry is a pointer to an ATQentry data structure. The CallAddr
  10070. field of the data structure holds a pointer to the routine that AppleTalk calls
  10071. for any AppleTalk transition event. The ATQentry data structure is described in
  10072. the preceding section, “The AppleTalk Transition Queue.”
  10073.  
  10074.    Result codes
  10075.           noErr           0         No error
  10076.  
  10077. FUNCTION LAPRmvATQ (theATQEntry: ATQEntryPtr): OSErr;
  10078.  
  10079.           _________________________________________________
  10080.  
  10081.            On entry                  D0: 24
  10082.                                              A0: pointer to AppleTalk Transition
  10083.                                              Queue entry
  10084.            On exit                     D0: result code
  10085.           _________________________________________________
  10086.  
  10087. The LAPRmvATQ function removes an entry from the AppleTalk Transition Queue. The
  10088. parameter theATQEntry is a pointer to an ATQentry data structure. 
  10089.  
  10090.    Note:  You must not call the LAPRmvATQ function at interrupt time or through
  10091.    a callback routine. This restriction is to prevent any routine from removing
  10092.    an
  10093.    entry from the AppleTalk Transition Queue while another routine is in the
  10094.    process of adding or removing an entry.
  10095.  
  10096.    Result codes
  10097.           noErr           0           No error
  10098.           qErr            –1           Queue element not found
  10099. _______________________________________________________________________________
  10100.  
  10101. æKY Sending…Messages…to…the…Appletalk…Transition…Queue
  10102. æC »Sending Messages to the Appletalk Transition Queue                   AppleTalk Manager
  10103. _______________________________________________________________________________
  10104.  
  10105. Whereas it is unlikely that opening the .MPP driver will adversely affect
  10106. another program, an application should never close the .MPP driver, because
  10107. another program might be using it. Under certain circumstances, however, the
  10108. system might close the .MPP driver. The system uses the .MPP driver’s
  10109. PATalkClosePrep function to send a permission-to-close transition to each
  10110. routine in the AppleTalk Transition Queue. This transition indicates that the
  10111. system intends to close the .MPP driver so that each routine in the queue has
  10112. the opportunity to deny permission to do so.
  10113.  
  10114. When the system calls the PATalkClosePrep function, any routine in the AppleTalk
  10115. Transition Queue that wishes to deny permission to close the .MPP driver may
  10116. return a pointer to a Pascal string. The Pascal string should be the name of the
  10117. application that placed the entry in the queue. If any routine in the AppleTalk
  10118. Transition Queue denies permission to close the .MPP driver, the PATalkClosePrep
  10119. function returns the result code closeErr.
  10120.  
  10121. If any routine denies permission to close the .MPP driver, the AppleTalk Manager
  10122. sends a cancel-close transition to every routine in the AppleTalk Transition
  10123. Queue that previously received the permission-to-close transition. The caller of
  10124. the PATalkClosePrep function may display a dialog box informing the user that
  10125. another application is using the .MPP driver and showing the name (if any)
  10126. returned by the AppleTalk Transition Queue routine. The dialog box gives the
  10127. user the option of canceling the request to close AppleTalk or of closing
  10128. AppleTalk anyway. 
  10129.  
  10130. If the user chooses to close AppleTalk despite the fact that an application is
  10131. using it, the system calls the MPPClose function. AppleTalk then calls each
  10132. application in the AppleTalk Transition Queue, this time informing each one that
  10133. AppleTalk is about to close. In this case, your AppleTalk Transition Queue
  10134. routine must prepare for the imminent closing of AppleTalk; it cannot deny
  10135. permission to the MPPClose function. 
  10136.  
  10137. FUNCTION PATalkClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  10138.  
  10139.    Parameter block
  10140.         Æ     26      csCode              word      always PATalkClosePrep
  10141.         ¨     28      appName        long        pointer to name of application 
  10142.                                                                      that
  10143.                                                                      denies
  10144.                                                                      request
  10145.  
  10146. The PATalkClosePrep function calls each routine listed in the AppleTalk
  10147. Transition Queue to request permission to close the .MPP driver. 
  10148.  
  10149. If a routine in the AppleTalk Transition Queue denies permission to close the
  10150. .MPP driver, that routine can return a pointer to a Pascal string. The Pascal
  10151. string should contain the name of the application that placed the entry in the
  10152. AppleTalk Transition Queue. The PATalkClosePrep function returns that pointer in
  10153. the appName field. The function also returns the result code closeErr,
  10154. indicating that the calling routine has been denied permission to close the .MPP
  10155. driver. The routine that called PATalkClosePrep can then display a dialog box
  10156. telling the user the name of the application that is currently using AppleTalk
  10157. and asking whether to close AppleTalk anyway. 
  10158.  
  10159. The csCode parameter is a routine selector; it is always equal to
  10160. PATalkClosePrep for this function.
  10161.  
  10162.    Result codes
  10163.           noErr                0         No error
  10164.           closeErr        –24         Permission to close .MPP driver was denied
  10165.  
  10166. _______________________________________________________________________________
  10167.  
  10168. æKY How…the…Appletalk…Manager…Calls…Your…Queue…Entry
  10169. æC »How the Appletalk Manager Calls Your Queue Entry                     AppleTalk Manager
  10170. _______________________________________________________________________________
  10171.  
  10172. When you have used the LAPAddATQ function to add an entry to the AppleTalk
  10173. Transition Queue, the AppleTalk Manager calls your entry when any of the
  10174. following events occurs:
  10175.  
  10176.   •  A routine opens the .MPP driver. 
  10177.  
  10178.   •  A routine closes the .MPP driver. 
  10179.  
  10180.   •  A routine calls the PATalkClosePrep function. 
  10181.  
  10182.   •  One of the routines in the AppleTalk Transition Queue denies permission for
  10183.       the routine that called the PATalkClosePrep function to close AppleTalk.
  10184.  
  10185.   •  An application calls the ATEvent or ATPreFlightEvent routines to send its
  10186.   own
  10187.       AppleTalk transition event to the entries in the AppleTalk Transition
  10188.       Queue.
  10189.  
  10190. When the AppleTalk Manager calls your AppleTalk Transition Queue routine, the
  10191. stack looks like this:
  10192.  
  10193. Chart 32-1 Contents of the stack on a call to an ATQ routine ø 
  10194.  
  10195. The first item on the stack (after the return address) is a routine selector.
  10196. There is one routine selector for each type of transition. The open,
  10197. prepare-to-close, permission-to-close, and cancel-close transitions each have a
  10198. single-digit routine selector; all other routine selectors for AppleTalk
  10199. transition events are 4-character codes. Codes starting with an uppercase letter
  10200. (A through Z) are reserved for use by developers. All other codes are reserved
  10201. for use by Apple Computer, Inc.
  10202.  
  10203.    Routine selector                                Transition
  10204.  
  10205.     $00 00 00 00                                         .MPP driver opened
  10206.     $00 00 00 02                                         .MPP driver about to
  10207.     close
  10208.     $00 00 00 03                                         PATalkClosePrep
  10209.     function has been called
  10210.     $00 00 00 04                                         Closing of .MPP driver
  10211.     has been canceled
  10212.     $41 xx xx xx —$5A xx xx xx             Reserved for use by developers
  10213.     all others                                            Reserved for use by
  10214.     Apple Computer
  10215.  
  10216. You can use the following constants for the standard AppleTalk transitions:
  10217.  
  10218. CONST  ATTransOpen        = 0;                {open transition}
  10219.        ATTransClose       = 2;                {prepare-to-close transition}
  10220.        ATTransClosePrep   = 3;                {permission-to-close 
  10221.                                                transition}
  10222.        ATTransCancelClose = 4;                {cancel-close transition} 
  10223.  
  10224. The second item passed to your routine on the stack is a pointer to your
  10225. routine’s entry in the AppleTalk Transition Queue. You can use this pointer to
  10226. get access to any fields at the end of the queue entry that you allocated for
  10227. your own use. The last item passed to your routine on the stack is a parameter
  10228. whose meaning depends on the type of transition. 
  10229.  
  10230. The interface between the AppleTalk Transition Queue and your routine follows
  10231. these conventions: Your routine must preserve all registers except D0, D1, D2,
  10232. A0, and A1; all parameters are passed on the stack as long words. Because your
  10233. routine might be called at interrupt time, your routine must not make any direct
  10234. or indirect calls to the Memory Manager and can’t depend on handles to unlocked
  10235. blocks being valid. If you want to use any of your application’s global
  10236. variables, you must save the contents of the A5 register before using the
  10237. variables, and you must restore the A5 register before your routine terminates.
  10238. These restrictions do not apply to the open transition or the prepare-to-close
  10239. transition.
  10240.  
  10241.    Note:  It is important that you return a 0 in the D0 register whenever you
  10242.    receive
  10243.    a transition event routine selector that you do not recognize or do not
  10244.    choose to
  10245.    handle. Returning a nonzero value in the D0 register might cause the system
  10246.    to
  10247.    cancel an attempt to close AppleTalk, for example, or might be misinterpreted
  10248.    in
  10249.    some other way. 
  10250.  
  10251.  
  10252. Open Transition 
  10253.  
  10254. When an application calls the MPPOpen function, the AppleTalk Manager first
  10255. attempts to open the .MPP driver. If the .MPP driver is already open, the
  10256. AppleTalk Manager does not call the AppleTalk Transition Queue. If the AppleTalk
  10257. Manager successfully opens the .MPP driver, it then calls every routine listed
  10258. in the AppleTalk Transition Queue with an open transition.
  10259.  
  10260. The third item on the stack for an open transition is a pointer to the start of
  10261. the Device Manager extended parameter block used by the routine that opened the
  10262. .MPP driver. This pointer is provided for your information only; you must not
  10263. change any of the fields in this parameter block. 
  10264.  
  10265. Your AppleTalk Transition Queue routine can perform any tasks you wish in
  10266. response to the notification that the .MPP driver has been opened, such as using
  10267. the Name-Binding Protocol (NBP) to register a name on the internet. Return 0 in
  10268. the D0 register to indicate that your routine executed with no error.
  10269.  
  10270.  
  10271. Prepare-to-Close Transistion
  10272.  
  10273. When any routine calls the MPPClose function to close the .MPP driver, the
  10274. AppleTalk Manager calls every routine listed in the AppleTalk Transition Queue
  10275. before the .MPP driver closes. If the .MPP driver is already closed when a
  10276. routine calls the MPPClose function, the AppleTalk Manager does not call the
  10277. routines in the AppleTalk Transition Queue.
  10278.  
  10279. When the AppleTalk Manager calls your routine for a prepare-to-close transition,
  10280. the third item on the stack is a NIL pointer.
  10281.  
  10282. Your routine can perform any tasks you wish to prepare for the imminent closing
  10283. of AppleTalk, such as ending a session with a remote terminal and informing the
  10284. user that the connection is being closed. You must return control to the
  10285. AppleTalk Manager as quickly as possible. Return 0 in the D0 register to
  10286. indicate that your routine executed with no error.
  10287.  
  10288.    Note:  When the AppleTalk Manager calls your routine with a prepare-to-close
  10289.    transition (that is, a routine selector of ATTransClose), you cannot prevent
  10290.    the
  10291.    .MPP driver from closing.
  10292.  
  10293.  
  10294. Permission-to-Close Transition 
  10295.  
  10296. When a routine calls the PATalkClosePrep function to inform the AppleTalk
  10297. Manager that it wants to close the .MPP driver, the AppleTalk Manager calls
  10298. every routine listed in the AppleTalk Transition Queue to request permission to
  10299. close the .MPP driver. 
  10300.  
  10301. When the AppleTalk Manager calls your routine to request permission to close the
  10302. .MPP driver, the third parameter on the stack is a pointer to a 4-byte buffer.
  10303. If you intend to deny the request to close AppleTalk, you should place in the
  10304. buffer a pointer to a Pascal string containing the name of your application. The
  10305. PATalkClosePrep function returns this pointer. The routine that called the
  10306. PATalkClosePrep function can then display a dialog box telling the user the name
  10307. of the application that is currently using AppleTalk.
  10308.  
  10309. Your routine can return either a function result of 0 in the D0 register,
  10310. indicating that it accepts the request to close, or a 1 in the D0 register,
  10311. indicating that it denies the request to close. Note that the Operating System
  10312. might elect to close AppleTalk anyway; for example, if the user grants
  10313. permission to close in response to a dialog box.
  10314.  
  10315. Because the AppleTalk Manager calls your routine again (with the routine
  10316. selector set to ATTransClose) before the .MPP driver actually closes, it is not
  10317. necessary for your routine to do anything other than grant or deny permission in
  10318. response to being called for a permission-to-close transition. However, you
  10319. might want to prohibit the users from opening new sessions or establishing new
  10320. connections while you are waiting for the .MPP driver to close.
  10321.  
  10322.  
  10323. Cancel-Close Transition 
  10324.  
  10325. When any routine in the AppleTalk Transition Queue denies permission for the
  10326. .MPP driver to close, the AppleTalk Manager calls each routine listed in the
  10327. AppleTalk Transition Queue that has already received the permission-to-close
  10328. transition to inform it that the request to close the .MPP driver has been
  10329. canceled. 
  10330.  
  10331. When the AppleTalk Manager calls your AppleTalk Transition Queue routine for a
  10332. cancel-close transition, the third item on the stack is a NIL pointer.
  10333.  
  10334. If your routine performed any tasks to prepare for the closing of AppleTalk, it
  10335. should reverse their effects when it is called with the routine selector set to
  10336. ATTransCancelClose. Return 0 in the D0 register to indicate that your routine
  10337. executed with no error.
  10338.  
  10339.  
  10340. Developer-Defined Transitions 
  10341.  
  10342. Any AppleTalk transition event code that begins with an uppercase letter (that
  10343. is, any value in the range $41 00 00 00  through $5A FF FF FF) indicates a
  10344. developer-defined event. You can use such events to send messages to your own
  10345. entries in the AppleTalk Transition Queue, or you can define events and make
  10346. them public for others to use. Because you cannot tell how the originator of
  10347. such an event might interpret a nonzero function result, you must always return
  10348. 0 in the D0 register for any AppleTalk transition event code that you do not
  10349. recognize.
  10350.  
  10351. When you return a nonzero result code for certain developer-defined transitions,
  10352. the AppleTalk Manager may call your AppleTalk Transition Queue routine a second
  10353. time with a cancel transition analogous to the cancel-close transition. 
  10354.  
  10355.  
  10356. _______________________________________________________________________________
  10357.  
  10358. æKY Defining…Your…Own…Appletalk…Transition
  10359. æC »Defining Your Own Appletalk Transition                               AppleTalk Manager
  10360. _______________________________________________________________________________
  10361.  
  10362. You can define your own AppleTalk transition to have any meaning you choose. For
  10363. example, you might want to call every routine in the AppleTalk Transition Queue
  10364. each time you open an AppleTalk Data Stream Protocol (ADSP) connection.
  10365.  
  10366. You can use either the ATEvent procedure or the ATPreFlightEvent function to
  10367. notify all of the routines in the AppleTalk Transition Queue that your AppleTalk
  10368. transition has occurred. Whereas the ATEvent procedure only calls the routines
  10369. in the queue with a transition event, the ATPreFlightEvent function also allows
  10370. each routine in the AppleTalk Transition Queue to return a result code and other
  10371. information to your calling routine.
  10372.  
  10373.    Note:  You can call the ATEvent and ATPreFlightEvent routines only at
  10374.    virtual-memory safe time. See the Memory Manager chapter in this volume for
  10375.    information on virtual memory. 
  10376.  
  10377. PROCEDURE ATEvent (event: LongInt; infoPtr: Ptr);
  10378.  
  10379. The ATEvent procedure calls all of the routines in the AppleTalk Transition
  10380. Queue with the AppleTalk transition event code you specify in the event
  10381. parameter. The AppleTalk transition event code can be any 4-character string
  10382. that starts with an uppercase letter; that is, any value in the range $41 00 00
  10383. 00  through $5A FF FF FF. You can use the infoPtr parameter to point to any
  10384. information that you want to make available to the AppleTalk Transition Queue
  10385. routines; for an ADSP-open transition, for example, you might pass a pointer to
  10386. the parameter block used by the dspOpen routine. If you do not want to pass any
  10387. information to the AppleTalk Transition Queue routines, set the infoPtr
  10388. parameter to NIL.
  10389.  
  10390. FUNCTION ATPreFlightEvent (event,cancel: LongInt; infoPtr: Ptr) : OSErr; 
  10391.  
  10392. The ATPreFlightEvent function calls all of the routines in the AppleTalk
  10393. Transition Queue with the AppleTalk transition event code you specify in the
  10394. event parameter. If any routine in the AppleTalk Transition Queue returns a
  10395. nonzero function result, the ATPreFlightEvent function calls each of the
  10396. routines that it has already called, this time with the AppleTalk transition
  10397. event code you specify in the cancel parameter. The AppleTalk transition event
  10398. codes can be any 4-character strings that start with an uppercase letter; that
  10399. is, any values in the range $41 00 00 00  through $5A FF FF FF. You can use the
  10400. infoPtr parameter to point to any information that you want to make available to
  10401. the AppleTalk Transition Queue routines. If you do not want to pass any
  10402. information to the AppleTalk Transition Queue routines, set the infoPtr
  10403. parameter to NIL.
  10404.  
  10405.    Result codes
  10406.           noErr          0         No error, or unrecognized event code
  10407.  
  10408.    Note:  AppleTalk transitions defined by developers might return other result
  10409.    codes.
  10410.  
  10411.  
  10412. _______________________________________________________________________________
  10413.  
  10414. æKY The…LAP…Manager…802.2…Protocol
  10415. æC »The LAP Manager 802.2 Protocol                                       AppleTalk Manager
  10416. _______________________________________________________________________________
  10417.  
  10418. The Institute of Electrical and Electronics Engineers (IEEE) has defined a
  10419. series of communications protocols for use on a variety of networks. At the
  10420. physical level, these protocols include the 802.3 CSMA/CD protocol, the 802.4
  10421. token bus protocol, and the 802.5 token ring protocol. At the data link level,
  10422. you access these protocols through another IEEE protocol, the 802.2 protocol.
  10423. The AppleTalk LAP Manager includes two routines that allow you to attach and
  10424. detach protocol handlers for 802.2 Type 1 data packets: the L802Attach and
  10425. L802Detach routines. You can write an application that reads 802.2 Type 1 data
  10426. packets and use the L802Attach routine to install your application as a client
  10427. of the LAP Manager. The ANSI/IEEE standards for the 802 protocols are published
  10428. by the IEEE.
  10429.  
  10430. The first 14 bytes of a packet sent or received by the .ENET driver constitute
  10431. the header. The first 12 bytes consist of the destination and source data-link
  10432. addresses, such as the Ethernet hardware addresses. If the value of the last 2
  10433. bytes in the header is greater than 1500, then the .ENET driver treats that
  10434. field as an Ethernet protocol type discriminator. See “The .ENET Driver,” later
  10435. in this chapter, for more information on Ethernet protocols. If the value of the
  10436. last 2 bytes in the header is less than or equal to 1500, then the packet is an
  10437. 802.3 protocol packet and this field indicates the length of the 802.3 data. The
  10438. .ENET driver passes all 802.3 packets to the LAP Manager.
  10439.  
  10440. The LAP Manager receives the entire 802.3 packet from the .ENET driver. The
  10441. first 3 bytes of the 802.3 data constitute the header for the 802.2 protocol.
  10442. The first byte of the 802.2 header is known as the destination service access
  10443. point (DSAP). If the DSAP field is equal to $AA, then the first 5 bytes of the
  10444. 802.2 data constitute a protocol discriminator known as the subnetwork access
  10445. protocol (SNAP) type. If the SNAP type field is $00000080F3, indicating the
  10446. AppleTalk Address Resolution Protocol (AARP), then the next 4 bytes of the 802.2
  10447. data constitute a third type field, the AARP packet type. AARP is discussed in
  10448. Inside AppleTalk.
  10449.  
  10450. The first packet header in Figure 32-4, for example, indicates an Ethernet
  10451. packet containing AppleTalk Phase 1 data. The .ENET driver would deliver this
  10452. packet to the AppleTalk Phase 1 protocol handler.
  10453.  
  10454. By contrast, the second data packet header in the figure indicates an 802.3
  10455. packet containing AppleTalk Phase 2 data. The .ENET driver would deliver this
  10456. packet to the AppleTalk Phase 2 LAP Manager. 
  10457.  
  10458. Similarly, the third data packet header in Figure 32-4 indicates an 802.3 packet
  10459. to be delivered to the Phase 2 EtherTalk AARP handler:
  10460.  
  10461. ¿ Figure 32-4   AppleTalk Ethernet packet formats ø 
  10462.  
  10463. When you call the L802Attach routine, you provide a pointer to your protocol
  10464. handler, the reference number of the .ENET driver, and a pointer to a string
  10465. containing one or more type fields. The type fields indicate the DSAP value and
  10466. any other protocol type fields (such as the SNAP type and the AARP type). The
  10467. LAP Manager delivers to your protocol handler any 802.2 data packets that have
  10468. the protocol type you specify. 
  10469.  
  10470. _______________________________________________________________________________
  10471.  
  10472. æKY Attaching…and…Detaching…802.2…Protocol…Handlers
  10473. æC »Attaching and Detaching 802.2 Protocol Handlers                      AppleTalk Manager
  10474. _______________________________________________________________________________
  10475.  
  10476. You can attach to the LAP Manager your own protocol handler for 802.2 protocols.
  10477. The LAP Manager has permanent handlers for certain types of EtherTalk packets.
  10478. You cannot replace or override the permanent LAP Manager protocol handlers. 
  10479.  
  10480. There are no high-level interfaces for the LAP Manager 802.2 protocol routines.
  10481. You call these routines from assembly language by placing a routine selector in
  10482. the D0 register and executing a JSR instruction to an offset 2 bytes past the
  10483. start of the LAP Manager. The start of the LAP Manager is contained in the
  10484. global variable LAPMgrPtr ($B18). 
  10485.  
  10486. Before you call these routines, you must place the reference number of the .ENET
  10487. driver in the D2 register and a pointer to the protocol type specification in
  10488. the A1 register. Before you call the L802Attach routine, you must also place a
  10489. pointer to your protocol handler in the A0 register. Both routines return a
  10490. nonzero value in the D0 register if there is an error. 
  10491.  
  10492. Listing 32-1 shows how to call a LAP Manager L802.2 routine from assembly
  10493. language.
  10494.  
  10495. ¿ Listing 32-1   Calling a LAP Manager L802.2 routine from assembly language
  10496.  
  10497. LAPMgrPtr   EQU     $B18            ;entry point for LAP Manager
  10498. LAPMgrCall  EQU     2               ;offset to LAP Manager routines
  10499. L802Entry   EQU     *               ;L802 routine entry
  10500. ...
  10501.  
  10502.             MOVEQ   #RSel,D0        ;place routine selector 
  10503.                                     ; in D0
  10504.             MOVEQ   #refNum,D2      ;place driver reference number
  10505.                                     ; in D2
  10506.             MOVE.L  PHndlrPtr,A0    ;put pointer to protocol 
  10507.                                     ; handler in A0 (L802Attach 
  10508.                                     ; only)
  10509.             MOVE.L  PSpecPtr,A1     ;put pointer to protocol 
  10510.                                     ; specification in A1)
  10511.             MOVE.L  LAPMgrPtr,An    ;put pointer to LAP Mgr in An
  10512.             JSR     LAPMgrCall(An)  ;jump to start of LAP Mgr
  10513.                     ; routines
  10514.  
  10515.  
  10516. L802Attach
  10517.           _______________________________________________
  10518.            On entry                   D0: 21
  10519.                                               D2: reference number of .ENET
  10520.                                               driver
  10521.                                               A0: pointer to your protocol
  10522.                                               handler
  10523.                                               A1: pointer to protocol
  10524.                                               specification
  10525.  
  10526.            On exit                     D0: nonzero if error 
  10527.           _______________________________________________
  10528.  
  10529. The L802Attach routine attaches to the LAP Manager a protocol handler for a
  10530. specific IEEE 802.2 protocol type.
  10531.  
  10532. Before calling this routine, you must put the value 21 in the D0 register and
  10533. the reference number of the .ENET driver in the D2 register. The .ENET driver
  10534. reference number is returned by the OpenSlot function. If you are not using the
  10535. .ENET driver or a driver that uses the same interface as the .ENET driver, you
  10536. cannot use the L802Attach routine. 
  10537.  
  10538. You must put a pointer to your protocol handler in the A0 register and a pointer
  10539. to the protocol-type specification for this protocol handler in the A1 register.
  10540. The protocol-type specification consists of one or more protocol-type fields,
  10541. each preceded by a length byte. The LAP Manager reads the protocol-type fields
  10542. in the 802.2 data packet header to determine to which protocol handler (if any)
  10543. to deliver the packet. The first type field in your protocol specification is
  10544. the 1-byte DSAP. If the DSAP type field is equal to $AA, then the protocol-type
  10545. specification must contain a second type field, the 5-byte SNAP type. If the
  10546. SNAP type field is $00000080F3, indicating the AppleTalk Address Resolution
  10547. Protocol (AARP), then the protocol-type specification must contain a third type
  10548. field, the 4byte AARP protocol type. Terminate the list of protocol-type fields
  10549. with a byte of zeros.
  10550.  
  10551. The following protocol-type specification, for example, is for the permanent LAP
  10552. Manager protocol handler for an 802.3 packet containing AppleTalk data. The
  10553. .ENET driver would deliver this packet to the AppleTalk Phase 2 LAP Manager. The
  10554. first byte, $01, is the length byte for the first protocol-type field (the DSAP
  10555. type field), $AA. The third byte, $05, is the length byte for the next
  10556. protocol-type field, the SNAP. The final byte ($00) terminates the type
  10557. specification.
  10558.  
  10559. 01 AA 05 08 00 07 80 9B 00
  10560.  
  10561. The following protocol-type specification is for the permanent LAP Manager
  10562. protocol handler for an 802.3 packet to be delivered to the EtherTalk AARP
  10563. handler. Notice that the SNAP field is followed by an additional type field, the
  10564. AARP protocol type.
  10565.  
  10566. 01 AA 05 00 00 00 80 F3 04 00 01 80 9B 00
  10567.  
  10568.    Note:  The DSAP value of $AA is reserved for use with protocol-type
  10569.    specifications that include a SNAP field. The SNAP value of $08 00 07 80 9B
  10570.    is
  10571.    reserved for AppleTalk data. The SNAP value of $00 00 00 80 F3 is reserved
  10572.    for
  10573.    AARP data. The AARP protocol type value of $00 01 80 9B is reserved for
  10574.    EtherTalk AARP packets.  
  10575.  
  10576. See the ANSI/IEEE standard 802.2 for more information about 802.2 protocols, and
  10577. see Inside AppleTalk for more information about AARP.
  10578.  
  10579.  
  10580. L802Detach
  10581.           ________________________________________________
  10582.            On entry                     D0: 22
  10583.                                                 D2: reference number of .ENET
  10584.                                                 driver
  10585.                                                 A1: pointer to protocol
  10586.                                                 specification
  10587.  
  10588.            On exit                        D0: nonzero if error 
  10589.           ________________________________________________
  10590.  
  10591. The L802Detach routine detaches from the LAP Manager a protocol handler for a
  10592. specific IEEE 802.2 protocol type.
  10593.  
  10594. Before calling this routine, you must put the value 22 in the D0 register and
  10595. the reference number of the .ENET driver in the D2 register. The .ENET driver
  10596. reference number is returned by the OpenSlot function. If you are not using the
  10597. .ENET driver or a driver that uses the same interface as the .ENET driver, you
  10598. cannot use the L802Detach routine. 
  10599.  
  10600. You must put a pointer to the protocol-type specification for this protocol
  10601. handler in the A1 register. You must specify exactly the same protocol type as
  10602. you specified for the L802Attach routine when you attached the protocol handler.
  10603.  
  10604. _______________________________________________________________________________
  10605.  
  10606. æKY The….ATP…Driver…Volume…VI
  10607. æC »The .ATP Driver Volume VI                                            AppleTalk Manager
  10608. _______________________________________________________________________________
  10609.  
  10610. AppleTalk Phase 2 includes two changes to the .ATP driver: you can now cancel
  10611. all calls to the ATPGetRequest function that are pending execution, and you can
  10612. now set the release timer for AppleTalk Transaction Protocol (ATP) exactly-once
  10613. (XO) service to one of five different values. 
  10614.  
  10615. _______________________________________________________________________________
  10616.  
  10617. æKY Canceling…All…Calls…to…the…Atpgetrequest…Function
  10618. æC »Canceling All Calls to the Atpgetrequest Function                    AppleTalk Manager
  10619. _______________________________________________________________________________
  10620.  
  10621. The ATPGetRequest function sets a socket to receive a request sent by another
  10622. socket. If you call the ATPGetRequest function asynchronously, you can have
  10623. several calls to the function simultaneously pending execution. The
  10624. ATPKillAllGetReq function cancels all calls to the ATPGetRequest function
  10625. pending for a specific socket without closing the socket. 
  10626.  
  10627. FUNCTION ATPKillAllGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  10628.  
  10629.    Parameter block
  10630.         Æ     26      csCode            word     always ATPKillAllGetReq
  10631.         Æ     28      atpSocket        byte      socket for which to cancel all
  10632.         calls 
  10633.                                                                  to
  10634.                                                                  ATPGetRequest
  10635.  
  10636. The ATPKillAllGetReq function cancels all pending asynchronous calls to the
  10637. ATPGetRequest function for the socket you specify with the atpSocket parameter.
  10638. The ATPKillAllGetReq function also calls the completion routine for each call to
  10639. the ATPGetRequest function with the result code reqAborted (–1105) in the D0
  10640. register. 
  10641.  
  10642. Unlike the ATPCloseSocket function, the ATPKillAllGetReq function does not close
  10643. the socket. You should call the ATPKillAllGetReq function before closing a
  10644. socket. The csCode parameter is a routine selector, automatically set by the MPW
  10645. interface. It is always equal to ATPKillAllGetReq for this function.
  10646.  
  10647.    Result codes
  10648.         noErr                         0    No error
  10649.         cbNotFound    –1102    Control block not found; no pending asynchronous
  10650.         calls
  10651. _______________________________________________________________________________
  10652.  
  10653. æKY Setting…the…Timeout…Value…for…the…Atp…Release…Timer
  10654. æC »Setting the Timeout Value for the Atp Release Timer                  AppleTalk Manager
  10655. _______________________________________________________________________________
  10656.  
  10657. The .ATP driver maintains a timer, called the release timer , for each call to
  10658. the PSendResponse function that is part of an exactly-once (XO) transaction. If
  10659. the timer expires before the transaction is complete (that is, before the socket
  10660. receives the transaction release packet), the driver completes the PSendResponse
  10661. function. Before AppleTalk Phase 2, the release timer was always set to 30
  10662. seconds. To set the other connection end’s release timer to another value, set
  10663. bit 2 of the atpFlags field in the parameter block for the PSendRequest or the
  10664. PNSendRequest function and add a new byte field to the parameter block at offset
  10665. 50—the TRelTime field. (The PSendRequest and PNSendRequest functions use the
  10666. SendRequestParm variant of the ATP parameter block.) Here is the ATP parameter
  10667. block for the PSendRequest and PNSendRequest functions:
  10668.  
  10669.    TYPE ATPParamBlock =
  10670.         PACKED RECORD                     {extended parameter block } 
  10671.                                           { for PSendRequest and }
  10672.                                           { PNSendRequest}
  10673.            qLink:           QElemPtr;     {next queue entry}
  10674.            qType:           Integer;      {queue type}
  10675.            ioTrap:          Integer;      {routine trap}
  10676.            ioCmdAddr:       Ptr;          {routine address}
  10677.            ioCompletion:    ProcPtr;      {completion routine}
  10678.            ioResult:        OsErr;        {result code}
  10679.            userData:        LongInt;      {ATP user bytes}
  10680.            reqTID:          Integer;      {request transaction ID}
  10681.            ioRefNum:        Integer;      {driver reference number}
  10682.            csCode:          Integer;      {primary command code}
  10683.            atpSocket:       Byte;         {currBitMap or socket number}
  10684.            atpFlags:        Byte;         {control information - set bit 2 }
  10685.                                           { for extended parameter block}
  10686.            addrBlock:       AddrBlock;    {source socket address}
  10687.            reqLength:       Integer;      {request size in bytes}
  10688.            reqPointer:      Ptr;          {pointer to request data}
  10689.            bdsPointer:      Ptr;          {pointer to response Buffer }
  10690.                                           { Data Structure}
  10691.            numOfBuffs:      Byte;         {number of responses expected}
  10692.            timeOutVal:      Byte;         {timeout interval}
  10693.            numOfResps:      Byte;         {number of responses }
  10694.                                           { actually received}
  10695.            retryCount:      Byte;         {number of retries}
  10696.            intBuff:         Integer;      {used internally for PNSendRequest}
  10697.            TRelTime:        Byte          {release timer setting}
  10698.         end;
  10699.  
  10700. The lower three bits of the TRelTime field indicate the time to which the
  10701. release timer is to be set, as follows:
  10702.  
  10703.    TRelTime field                   Setting of release timer
  10704.  
  10705.     000                                         30 seconds
  10706.     001                                         1 minute
  10707.     010                                         2 minutes
  10708.     011                                         4 minutes
  10709.     100                                         8 minutes
  10710.  
  10711.    Note:  The nodes at both ends of the ATP connection must be running AppleTalk
  10712.    Phase 2 drivers for this feature to work.
  10713.  
  10714. XO service, the release timer, and the SendRequest function are described in the
  10715. AppleTalk Manager chapter of Volume II. The ATP parameter block and the
  10716. PNSendRequest function are described in the AppleTalk Manager chapter of Volume
  10717. V.
  10718.  
  10719. _______________________________________________________________________________
  10720.  
  10721. æKY The….XPP…Driver…Volume…VI
  10722. æC »The .XPP Driver Volume VI                                            AppleTalk Manager
  10723. _______________________________________________________________________________
  10724.  
  10725. The .XPP driver provides these functions that return information about zones:
  10726.  
  10727.   •  The GetMyZone function returns the AppleTalk zone name of the node on
  10728.       which your application is running. This function works for both extended
  10729.       and
  10730.       nonextended networks.
  10731.  
  10732.   •  The GetLocalZones function returns a list of zone names on the network that
  10733.       includes the node on which your application is running. This function
  10734.       works
  10735.       for extended networks only.
  10736.  
  10737.   •  The GetZoneList function returns a complete list of zones on the internet.
  10738.  
  10739.    Note:  Before the AppleTalk Phase 2 version of the .XPP driver, you had to
  10740.    use
  10741.    AppleTalk Transaction Protocol (ATP) to obtain zone information and request
  10742.    it
  10743.    directly from a router. The Zone Information Protocol (ZIP) functions
  10744.    provided
  10745.    by the new version of the .XPP driver make it much easier for you to obtain
  10746.    this
  10747.    information. To ensure compatibility with future versions of AppleTalk, you
  10748.    should always use the functions described in this section to obtain zone
  10749.    information. 
  10750.  
  10751. For the GetMyZone, GetLocalZones, and GetZoneList functions, the .XPP driver
  10752. uses the xCallParam variant to the XPP parameter block.
  10753.  
  10754.    TYPE XPPParamBlock = 
  10755.         PACKED RECORD
  10756.            qLink:          QElemPtr;   {next queue entry}
  10757.            qType:          Integer;    {queue type}
  10758.            ioTrap:         Integer;    {routine trap}
  10759.            ioCmdAddr:      Ptr;        {routine address}
  10760.            ioCompletion:   ProcPtr;    {completion routine}
  10761.            ioResult:       OsErr;      {result code}
  10762.            cmdResult:      LongInt;    {command result}
  10763.            ioVRefNum:      Integer;    {volume reference number}
  10764.            ioRefNum:       Integer;    {driver reference number}
  10765.            csCode:         Integer;    {primary command code}
  10766.            CASE XPPPrmBlkType OF
  10767.               xCallParam
  10768.                 xppSubCode:   Integer;    {secondary command code}
  10769.                 xppTimeOut:   Byte;       {timeout period for .XPP}
  10770.                 xppRetry:     Byte;       {retry count}
  10771.                 filler1:      Integer;    {reserved}
  10772.                 zipBuffPtr:   Ptr;        {returned zone names}
  10773.                 zipNumZones:  Integer;    {number of zones returned}
  10774.                 zipLastFlag:  Byte;       {nonzero when all zone }
  10775.                                           { names have been returned}
  10776.                 filler2       Byte;       {reserved}
  10777.                 zipInfoField: packed array[1..70] of Byte
  10778.                                           {reserved for use by .XPP}
  10779.         END;
  10780.         XPPParmBlkPtr = ^XPPParamBlock;
  10781.  
  10782. As for all other AppleTalk Manager preferred interface functions, the MPW
  10783. interface calls the Device Manager PBControl function to implement these ZIP
  10784. protocol functions. The qLink, qType, ioTrap, ioCmdAddr, and ioVRefNum fields
  10785. are filled in by the Device Manager; your application should not have to set or
  10786. read these fields. The ioResult field returns the result of the function. If you
  10787. call the function asynchronously, the Device Manager sets this field to 1 as
  10788. soon as you call the function, and it changes the field to the actual result
  10789. code when the function completes execution. The ioCompletion field is a pointer
  10790. to a completion routine that you can provide; the Device Manager calls your
  10791. completion routine when it completes execution of the PBControl function. If you
  10792. are not providing a completion routine, specify NIL for this field. 
  10793.  
  10794. The value of the ioRefNum field is returned by the OpenDriver function; you must
  10795. provide this value in each call to an .XPP driver routine. The csCode and
  10796. xppSubCode fields specify the command to be executed; the MPW Pascal interface
  10797. fills in these fields for you.The .XPP zone information functions do not use the
  10798. cmdResult field.
  10799.  
  10800. _______________________________________________________________________________
  10801.  
  10802. æKY Using…the….XPP…Driver…to…Obtain…Information…About…Zones
  10803. æC »Using the .XPP Driver to Obtain Information About Zones              AppleTalk Manager
  10804. _______________________________________________________________________________
  10805.  
  10806. The Zone Information Protocol (ZIP) obtains the zone information by using the
  10807. AppleTalk Transaction Protocol (ATP) to send an information request to a router.
  10808. The xppTimeOut field specifies the amount of time, in seconds, that the .ATP
  10809. driver should wait between attempts to obtain the data. The xppRetry field
  10810. specifies the number of times the .ATP driver should attempt to obtain the data
  10811. before returning the reqFailed (request failed) result code. 
  10812.  
  10813. The zipBuffPtr field is a pointer to a data buffer that you must allocate. This
  10814. buffer must be 578 bytes for the GetZoneList and GetLocalZones functions and 33
  10815. bytes for the GetMyZone function. ZIP returns the zone names (as a packed array
  10816. of packed Pascal strings) into this buffer. The zipNumZones field returns the
  10817. actual number of zone names that ZIP placed in the buffer. You must set the
  10818. zipLastFlag field to 0 (FALSE) before you execute the GetZoneList or
  10819. GetLocalZones functions. If the zipLastFlag parameter is still 0 when the
  10820. command has completed execution, then ZIP is waiting to return more zone names.
  10821. In this case you must empty the buffer (or allocate a new one) and call the
  10822. GetZoneList or GetLocalZones function again immediately. When there are no more
  10823. zone names to return, ZIP sets the zipLastFlag field to a nonzero (TRUE) value.
  10824.  
  10825. The zipInfoField field is a 70-byte data buffer that you must allocate for use
  10826. by the .XPP driver. The first time you call any of these functions, you must set
  10827. the first word of this field to 0. You must not change any values in this field
  10828. subsequently.
  10829.  
  10830. Listing 32-2 illustrates the use of the GetZoneList function. The GetLocalZones
  10831. function operates in exactly the same fashion.
  10832.  
  10833. ¿ Listing 32-2   Using the GetZoneList function
  10834.  
  10835. PROCEDURE doGetZoneList;
  10836.  
  10837. VAR
  10838.    myXPPPB:  XPPParamBlock;      {.XPP parameter block}
  10839.    myErr:    OSErr;  
  10840.   
  10841. BEGIN
  10842.    WITH myXPPPB DO
  10843.    BEGIN
  10844.       xppTimeOut := 3;               {timeout period for .XPP}
  10845.       xppRetry := 4;                 {retry count}
  10846.       zipBuffPtr := NewPtr(578);     {zone names returned here}
  10847.       zipLastFlag := 0;              {set to 0 the first time through}
  10848.       zipInfoField[1] := 0;
  10849.       zipInfoField[2] := 0;          {first word is 0 the first }
  10850.                                      { time through}
  10851.   END;
  10852.   myErr := noErr;
  10853.  
  10854. {Check the zipNumZones field to determine how many zone names }
  10855. { have been returned in the buffer.  Append the zone names to the }
  10856. { end of your own buffer before returning to read more zone names.}
  10857.  
  10858.   {loop to get all of the zone names}
  10859.   WHILE (myXPPPB.zipLastFlag = 0) & (myErr = noErr) DO
  10860.   BEGIN
  10861.      myErr := GetZoneList(@myXPPPB, FALSE);
  10862.      EmptyDataBuf(@myXPPPB);      {your routine to empty }
  10863.                                   { data buffer}
  10864.   END;
  10865.   YourZIPProc(@myXPPPB);          {your routine to process names}
  10866.   IF myErr <> noErr THEN DoError(myErr);  
  10867.                                   {there's an error}
  10868.   DisposPtr(myXPPPB.zipBuffPtr);  {give space back}
  10869. END;
  10870.  
  10871. Listing 32-3 illustrates the use of the GetMyZone function. 
  10872.  
  10873. ¿ Listing 32-3   Using the GetMyZone function
  10874.  
  10875. PROCEDURE doGetMyZone;
  10876.  
  10877. VAR
  10878.    myXPPPB:      XPPParamBlock;    {.XPP parameter block}
  10879.    myZoneName:   ARRAY[1..33] OF CHAR;
  10880.    myErr:        OSErr;  
  10881.   
  10882. BEGIN 
  10883.    WITH myXPPPB DO
  10884.    BEGIN
  10885.       xppTimeOut := 3;            {timeout period for .XPP}
  10886.       xppRetry := 4;              {retry count}
  10887.       zipBuffPtr := @myZoneName;  {zone name returned here}
  10888.       zipInfoField[1] := 0;
  10889.       zipInfoField[2] := 0;       {first word is 0 the first }
  10890.                                   { time through}
  10891.   END;
  10892.   myErr := GetMyZone(@myXPPPB, FALSE);
  10893.   IF myErr <> noErr THEN DoError(myErr);  
  10894.                                   {there's an error}
  10895. END;                
  10896. _______________________________________________________________________________
  10897.  
  10898. æKY Obtaining…Zone…Information
  10899. æC »Obtaining Zone Information                                           AppleTalk Manager
  10900. _______________________________________________________________________________
  10901.  
  10902. The .XPP driver provides three functions that obtain information about zones.
  10903. All three functions use the Zone Information Protocol (ZIP) to return the names
  10904. of zones. 
  10905.  
  10906.           _________________________________________________
  10907.  
  10908.            Assembly-language note:  The .XPP driver functions all use the same 
  10909.            value (xCall, which is equal to 246) for the csCode parameter to the 
  10910.            XPP parameter block. The xCall routine uses the value of the 
  10911.            xppSubCode parameter to distinguish between the functions, as 
  10912.            follows:
  10913.  
  10914.             Function                    xppSubCode                    Value
  10915.             GetMyZone               zipGetMyZone                    7
  10916.             GetLocalZones          zipGetLocalZones              5
  10917.             GetZoneList               zipGetZoneList                  6
  10918.           _________________________________________________
  10919.  
  10920. FUNCTION GetMyZone (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  10921.  
  10922.    Parameter block
  10923.         ¨         16       ioResult                word        result code 
  10924.         Æ         26       csCode                   word        routine
  10925.         selector; always xCall
  10926.         Æ         28       xppSubCode         word        routine selector;
  10927.         zipGetMyZone
  10928.         Æ         30       xppTimeOut         byte         retry interval in
  10929.         seconds
  10930.         Æ         31       xppRetry                byte         retry count
  10931.         Æ         34      zipBuffPtr               long       pointer to data
  10932.         buffer
  10933.         Æ         42       zipInfoField  70    bytes       for use by ZIP; first
  10934.         word set to 0
  10935.  
  10936. The GetMyZone function returns only the AppleTalk zone name of the node on which
  10937. your application is running.
  10938.  
  10939. The ioResult parameter returns the result of the function. If you call the
  10940. function asynchronously, the function sets this field to 1 as soon as it begins
  10941. execution, and it changes the field to the actual result code when it completes
  10942. execution. The csCode and xppSubCode parameters are routine selectors and are
  10943. automatically set by the MPW interface to xCall and zipGetMyZone for this
  10944. function. The xppTimeOut field specifies the amount of time, in seconds, that
  10945. the .ATP driver should wait between attempts to obtain the data. A value of 3 or
  10946. 4 for the xppTimeOut field generally gives good results. The xppRetry field
  10947. specifies the number of times the .ATP driver should attempt to obtain the data
  10948. before returning the ReqFailed (request failed) result code. A value of 3 or 4
  10949. for the xppRetry field usually works well. 
  10950.  
  10951. The zipBuffPtr is a pointer to a 33-byte data buffer that you must allocate. ZIP
  10952. returns the zone name into this buffer as a Pascal string. The zipInfo field is
  10953. a 70-byte data buffer that you must allocate for use by ZIP. You must set the
  10954. first word of this buffer to 0 before you call the GetMyZone function.
  10955.  
  10956.    Result codes
  10957.           noErr                          0      No error
  10958.           noBridgeErr          –93      No router is available
  10959.           reqFailed            –1096      Request to contact router failed;
  10960.           retry count exceeded 
  10961.           tooManyReqs   –1097      Too many concurrent requests
  10962.           noDataArea      –1104      Too many outstanding ATP calls
  10963.  
  10964. FUNCTION GetLocalZones (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  10965.  
  10966.   Parameter block
  10967.        ¨  16       ioResult                 word      result code 
  10968.        Æ  26       csCode                    word      routine selector; always
  10969.        xCall
  10970.        Æ  28       xppSubCode          word      routine selector;
  10971.        zipGetLocalZones
  10972.        Æ  30       xppTimeOut          byte       retry interval in seconds
  10973.        Æ  31       xppRetry                 byte       retry count
  10974.        Æ  34       zipBuffPtr              long       pointer to data buffer
  10975.        ¨  38       zipNumZones      word     number of names returned
  10976.        ¨  40       zipLastFlag             byte       nonzero if no more names
  10977.        Æ  42        zipInfoField  70    bytes     for use by ZIP; first word set
  10978.        to 0
  10979.  
  10980. The GetLocalZones function returns a list of all the zone names on the local
  10981. network; that is, the network that includes the node on which your application
  10982. is running.
  10983.  
  10984. The ioResult parameter returns the result of the function. If you call the
  10985. function asynchronously, the function sets this field to 1 as soon as it begins
  10986. execution, and it changes the field to the actual result code when it completes
  10987. execution. The csCode and xppSubCode parameters are routine selectors and are
  10988. automatically set by the MPW interface to xCall and zipGetLocalZones for this
  10989. function. The xppTimeOut field specifies the amount of time, in seconds, that
  10990. the .ATP driver should wait between attempts to obtain the data. A value of 3 or
  10991. 4 for the xppTimeOut field generally gives good results. The xppRetry field
  10992. specifies the number of times the .ATP driver should attempt to obtain the data
  10993. before returning the ReqFailed (request failed) result code. A value of 3 or 4
  10994. for the xppRetry field usually works well.
  10995.  
  10996. The zipBuffPtr field is a pointer to a 578-byte data buffer that you must
  10997. allocate. ZIP returns the zone names into this buffer as a packed array of
  10998. packed Pascal strings. The zipNumZones parameter returns the number of zone
  10999. names that ZIP placed in the data buffer. 
  11000.  
  11001. The .XPP driver sets the zipLastFlag field to 1 if there are no more zone names
  11002. for your network. If the zipLastFlag field is still 0 when the GetLocalZones
  11003. function has completed execution, you must empty the data buffer pointed to by
  11004. the zipBuffPtr parameter and immediately call the GetLocalZones function again
  11005. without changing the value in the zipInfoField parameter. The zipInfoField
  11006. parameter is a 70-byte data buffer that you must allocate for use by ZIP. You
  11007. must set the first word of this buffer to 0 before you call the GetLocalZones
  11008. function the first time, and you must not change the contents of this field
  11009. thereafter.
  11010.  
  11011.    Result codes
  11012.          noErr                           0       No error
  11013.          noBridgeErr            –93      No router is available
  11014.          reqFailed              –1096      Request to contact router failed;
  11015.          retry count exceeded
  11016.          tooManyReqs     –1097      Too many concurrent requests
  11017.          noDataArea        –1104      Too many outstanding ATP calls
  11018.  
  11019. FUNCTION GetZoneList (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  11020.  
  11021.    Parameter block
  11022.         ¨      16       ioResult                word           result code 
  11023.         Æ      26       csCode                    word          routine
  11024.         selector; always xCall
  11025.         Æ      28       xppSubCode         word           routine selector;
  11026.         zipGetZoneList
  11027.         Æ      30      xppTimeOut          byte             retry interval in
  11028.         seconds
  11029.         Æ      31       xppRetry                byte             retry count
  11030.         Æ      34       zipBuffPtr             long             pointer to data
  11031.         buffer
  11032.         ¨      38       zipNumZones    word            number of names returned
  11033.         ¨      40       zipLastFlag            byte             nonzero if no
  11034.         more names
  11035.         Æ      42       zipInfoField         70 bytes        for use by ZIP;
  11036.         first word set to 0
  11037.  
  11038. The GetZoneList function returns a complete list of all the zone names on the
  11039. internet. To obtain a list of only the zone names on the local network, use the
  11040. GetLocalZones function instead. 
  11041.  
  11042. The ioResult parameter returns the result of the function. If you call the
  11043. function asynchronously, the function sets this field to 1 as soon as it begins
  11044. execution, and it changes the field to the actual result code when it completes
  11045. execution. The csCode and xppSubCode parameters are routine selectors and are
  11046. automatically set by the MPW interface to xCall and zipGetZoneList for this
  11047. function. The xppTimeOut field specifies the amount of time, in seconds, that
  11048. the .ATP driver should wait between attempts to obtain the data. A value of 3 or
  11049. 4 for the xppTimeOut field generally gives good results. The xppRetry field
  11050. specifies the number of times the .ATP driver should attempt to obtain the data
  11051. before returning the ReqFailed (request failed) result code. A value of 3 or 4
  11052. for the xppRetry field usually works well.
  11053.  
  11054. The zipBuffPtr field is a pointer to a 578-byte data buffer that you must
  11055. allocate. ZIP returns the zone names into this buffer as Pascal strings. The
  11056. zipNumZones parameter returns the number of zone names that ZIP placed in the
  11057. data buffer. 
  11058.  
  11059. The .XPP driver sets the zipLastFlag field to 1 if there are no more zone names
  11060. for the internet. If the zipLastFlag field is still 0 when the GetZoneList
  11061. function has completed execution, you must empty the data buffer pointed to by
  11062. the zipBuffPtr parameter and immediately call the GetZoneList function again
  11063. without changing the value in the zipInfoField parameter. The zipInfoField
  11064. parameter is a 70-byte data buffer that you must allocate for use by ZIP. You
  11065. must set the first word of this buffer to 0 before you call the GetZoneList
  11066. function the first time, and not change the contents of this field thereafter.
  11067.  
  11068. If you use the GetZoneList function on an nonextended network, it returns the
  11069. reqFailed result code.
  11070.  
  11071.    Result codes
  11072.           noErr                            0     No error
  11073.           noBridgeErr            –93     No router is available
  11074.           reqFailed              –1096     Request to contact router failed;
  11075.           retry count exceeded
  11076.           tooManyReqs      –1097     Too many concurrent requests
  11077.           noDataArea         –1104     Too many outstanding ATP calls
  11078. _______________________________________________________________________________
  11079.  
  11080. æKY Appletalk…Data…Stream…Protocol…(adsp)…Volume…VI
  11081. æC »Appletalk Data Stream Protocol (adsp) Volume VI                      AppleTalk Manager
  11082. _______________________________________________________________________________
  11083.  
  11084. One of the significant new features of AppleTalk included as part of system
  11085. software version 7.0 is the AppleTalk Data Stream Protocol (ADSP), which
  11086. provides a full-duplex data stream connection between two nodes in an AppleTalk
  11087. internet. Like the AppleTalk Session Protocol, Printer Access Protocol, and
  11088. AppleTalk Transaction Protocol, ADSP uses the Datagram Delivery Protocol to send
  11089. its data over the internet. Therefore, even though ADSP appears to its clients
  11090. to handle data as a stream of bytes, the data is actually transmitted and
  11091. received by DDP in packets. ADSP takes advantage of this fact by including
  11092. control and status information in the DDP packet header. You can use the .DSP
  11093. driver routines described in “.DSP Driver Routines,” later in this chapter, to
  11094. control an ADSP connection. The .DSP driver takes care of implementation of ADSP
  11095. for you. 
  11096.  
  11097. Every ADSP connection is between two sockets in an AppleTalk internet. Each
  11098. socket can maintain concurrent ADSP connections with several other sockets, but
  11099. there can be only one ADSP connection between any two sockets at one time. When
  11100. a pair of sockets establishes an ADSP connection, each socket client initializes
  11101. and maintains a certain amount of control and state information that it uses for
  11102. synchronizing communication with the other socket client and for error checking.
  11103.  
  11104.  
  11105. The combination of a socket and the ADSP information maintained by the socket
  11106. client is referred to as a connection end. When two connection ends establish
  11107. communication, the connection is considered an open connection. When both
  11108. connection ends terminate the link and dispose of the connection information
  11109. each maintains, the connection is considered a closed connection. If one
  11110. connection end is established but the other connection end is unreachable or has
  11111. disposed of its connection information, the connection is considered a half-open
  11112. connection. No communication can occur over a half-open or closed connection. To
  11113. prevent a half-open connection from tying up resources, ADSP automatically
  11114. closes any half-open connection that cannot reestablish communications within 2
  11115. minutes. 
  11116.  
  11117. _______________________________________________________________________________
  11118.  
  11119. æKY Using…ADSP
  11120. æC »Using ADSP                                                           AppleTalk Manager
  11121. _______________________________________________________________________________
  11122.  
  11123. You can use ADSP to implement a data stream connection between any two sockets
  11124. on an internet. (Note that although there can be only one ADSP connection
  11125. between any two sockets, a single socket can maintain connections with several
  11126. other sockets.) This section describes how to open, maintain, and close a
  11127. connection between two sockets on an internet. It also describes how to
  11128. establish and use a connection listener; that is, a connection end that waits
  11129. passively to receive a connection request and then passes the connection request
  11130. on to its client, the connection server. Finally, this section describes how to
  11131. write a routine (referred to as a user routine ) that ADSP calls when your
  11132. connection end receives an unsolicited connection event. 
  11133.  
  11134. _______________________________________________________________________________
  11135.  
  11136. æKY The…ADSP…Connection…Control…Block
  11137. æC »The ADSP Connection Control Block                                    AppleTalk Manager
  11138. _______________________________________________________________________________
  11139.  
  11140. When you establish an ADSP connection end, you must allocate a nonrelocatable
  11141. block of memory for, and provide a pointer to, a connection control block (CCB)
  11142. data structure, which is used by ADSP to store state information about the
  11143. connection end. You may read the fields in the CCB to obtain information about
  11144. the connection end, but you are not allowed to write to any of the fields except
  11145. one, the userFlags field. The CCB requires 242 bytes and is defined by the TRCCB
  11146. data type.
  11147.  
  11148.    TYPE TRCCB = 
  11149.         PACKED RECORD
  11150.            ccbLink:         TPCCB;            {link to next CCB}
  11151.            refNum:          Integer;          {reference number}
  11152.            state:           Integer;          {state of the connection end}
  11153.            userFlags:       Byte;             {user flags for connection}
  11154.            localSocket:     Byte;             {local socket number}
  11155.            remoteAddress:   AddrBlock;        {remote end internet address}
  11156.            attnCode:        Integer;          {attention code received}
  11157.            attnSize:        Integer;          {size of attention data}
  11158.            attnPtr:         Ptr;              {pointer to attention data}
  11159.            reserved:        PACKED ARRAY[1..220] OF Byte
  11160.                                               {reserved for use by ADSP}
  11161.         END;
  11162.  
  11163. The internet address of the remote connection end is defined in the TRCCB record
  11164. by the AddrBlock data type:
  11165.  
  11166. TYPE AddrBlock = 
  11167.      PACKED RECORD
  11168.        aNet:                Integer;          {network number}
  11169.        aNode:               Byte;             {node ID}
  11170.        aSocket:             Byte              {socket number}
  11171.      END; 
  11172.  
  11173. Field descriptions
  11174.  
  11175. ccbLink           A pointer to the next CCB. This field is for use by ADSP only.
  11176.  
  11177. refNum         The reference number of the CCB. This number is assigned by ADSP
  11178.                         when you establish the connection end.
  11179.  
  11180. state                The state of the connection end, as follows:
  11181.  
  11182.                          State                Value         Meaning
  11183.  
  11184.                          sListening       1                 The socket is a
  11185.                          connection listening socket;
  11186.                                                                       that is, a
  11187.                                                                       socket
  11188.                                                                       that
  11189.                                                                       accepts
  11190.                                                                       ADSP
  11191.                                                                       requests
  11192.                                                                       to
  11193.                                                                       open
  11194.  
  11195.                                                                       and passes
  11196.                                                                       them on to
  11197.                                                                       a
  11198.                                                                       socket
  11199.                                                                       client.
  11200.                                                                       This state
  11201.                                                                       is
  11202.                                                                       ordinarily
  11203.                                                                       used
  11204.                                                                       only by
  11205.                                                                       connection
  11206.                                                                       servers.
  11207.  
  11208.                           sPassive          2                 The socket client
  11209.                           is inactive but capable of
  11210.                                                                        accepting
  11211.                                                                        an ADSP
  11212.                                                                        request
  11213.                                                                        to open a
  11214.  
  11215.                                                                        Unlike a
  11216.  
  11217.                                                                        listening
  11218.                                                                        socket,
  11219.                                                                        which
  11220.                                                                        passes
  11221.                                                                        the
  11222.  
  11223.  
  11224.                                                                        request
  11225.                                                                        on to a
  11226.                                                                        routine
  11227.                                                                        that can
  11228.                                                                        establish
  11229.                                                                        the
  11230.  
  11231.                                                                        on any
  11232.                                                                        socket, a
  11233.                                                                        socket
  11234.                                                                        client in
  11235.                                                                        the
  11236.                                                                        sPassive
  11237.                                                                        state can
  11238.                                                                        accept an
  11239.  
  11240.                                                                        request
  11241.                                                                        only to
  11242.                                                                        establish
  11243.                                                                        itself as
  11244.                                                                        a
  11245.  
  11246.                                                                        end.
  11247.  
  11248.                            sOpening        3                The socket client
  11249.                            has sent an
  11250.  
  11251.                                                                        request
  11252.                                                                        and is
  11253.                                                                        waiting
  11254.                                                                        for
  11255.  
  11256.  
  11257.  
  11258.                             sOpen             4                 The connection
  11259.                             is open.
  11260.  
  11261.                             sClosing         5                 The socket client
  11262.                             has requested that ADSP
  11263.                                                                         close
  11264.                                                                         the
  11265.  
  11266.                                                                         and ADSP
  11267.                                                                         is
  11268.                                                                         sending
  11269.                                                                         data or
  11270.                                                                         waiting
  11271.                                                                         for
  11272.  
  11273.                                                                         of data
  11274.                                                                         it has
  11275.                                                                         sent
  11276.                                                                         before
  11277.                                                                         closing
  11278.                                                                         the
  11279.  
  11280.  
  11281.  
  11282.                             sClosed            6                Either
  11283.                             connection end or ADSP has closed
  11284.                                                                         the
  11285.  
  11286.  
  11287.  
  11288. userFlags          Flags that indicate an unsolicited connection event has
  11289. occurred. An
  11290.                            unsolicited connection event is an event initiated by
  11291.                            ADSP or the
  11292.                            remote connection end that is not in response to any
  11293.                            .DSP routine
  11294.                            that you executed.  .i.AppleTalk Data Stream
  11295.                            Protocol:user flags 32-
  11296.  
  11297.                            Each time an unsolicited connection event occurs,
  11298.                            ADSP sets a flag
  11299.                            in the userFlags field of the CCB and calls the
  11300.                            routine you specified
  11301.                            in the userRoutine parameter to the dspInit routine
  11302.                            (if any). The       
  11303.                            user routine must read the userFlags field and then
  11304.                            clear the flag to
  11305.                            0. ADSP cannot notify your routine of future events
  11306.                            unless you clear
  11307.                            the flag after each event.
  11308.  
  11309.                            ADSP recognizes four types of unsolicited connection
  11310.                            events, one
  11311.                             corresponding to each of the flags in this field.
  11312.                             The events and flags
  11313.                             are defined as follows, where bit 7 is the most
  11314.                             significant bit:
  11315.  
  11316.                             Event              Flag bit          Meaning
  11317.  
  11318.                               eClosed            7                    ADSP has
  11319.                               been informed by the remote
  11320.  
  11321.  
  11322.  
  11323.  
  11324.  
  11325.  
  11326.  
  11327.  
  11328.  
  11329.  
  11330.  
  11331.  
  11332.  
  11333.  
  11334.  
  11335.                               eTearDown      6                  ADSP has
  11336.                               determined that the remote
  11337.  
  11338.  
  11339.                                                                               is
  11340.  
  11341.  
  11342.  
  11343.                                                                               so
  11344.  
  11345.  
  11346.  
  11347.  
  11348.  
  11349.  
  11350.                                eAttention       5                  ADSP has
  11351.                                received an attention
  11352.  
  11353.  
  11354.  
  11355.  
  11356.  
  11357.  
  11358.  
  11359.  
  11360.  
  11361.                               eFwdReset         4                 ADSP has
  11362.                               received a forward reset
  11363.  
  11364.  
  11365.  
  11366.  
  11367.  
  11368.  
  11369.  
  11370.  
  11371.  
  11372.  
  11373.  
  11374.  
  11375.  
  11376.  
  11377.  
  11378.  
  11379.  
  11380.  
  11381.                                                                               in
  11382.  
  11383.  
  11384.  
  11385.  
  11386.  
  11387.  
  11388.  
  11389.  
  11390.  
  11391.  
  11392.  
  11393.  
  11394.  
  11395.  
  11396.                                none                   3–0            Reserved.
  11397.  
  11398. localSocket          The socket number through which DDP transmits and receives 
  11399.                                the ADSP packets.
  11400.  
  11401. remoteAddress   The internet address of the socket used by the remote connection
  11402.                                 end.
  11403.  
  11404. attnCode               The attention code received by ADSP when the remote
  11405.                                 connection end sends an attention message.
  11406.  
  11407. attnSize                 The size of the attention message received by ADSP when
  11408. the
  11409.                                 remote connection end sends an attention
  11410.                                 message.
  11411.  
  11412. attnPtr                    A pointer to a buffer containing the attention
  11413. message received
  11414.                                  by ADSP from the remote connection end.
  11415.  
  11416. reserved                 A data buffer reserved for use by ADSP.
  11417.  
  11418. _______________________________________________________________________________
  11419.  
  11420. æKY The….DSP…Parameter…Block
  11421. æC »The .DSP Parameter Block                                             AppleTalk Manager
  11422. _______________________________________________________________________________
  11423.  
  11424. You execute the .DSP routines by calling the Device Manager’s PBControl
  11425. function. Each time you call a .DSP routine, you provide a pointer to a
  11426. parameter block that includes all of the parameters needed by that command. 
  11427.  
  11428. The .DSP parameter block, defined by the DSPParamBlock data type, is a variant
  11429. parameter block for the PBControl function.
  11430.  
  11431.    TYPE DSPParamBlock = 
  11432.        PACKED RECORD
  11433.           qLink:            QElemPtr;        {next queue entry}
  11434.           qType:            Integer;         {queue type}
  11435.           ioTrap:           Integer;         {routine trap}
  11436.           ioCmdAddr:        Ptr;             {routine address}
  11437.           ioCompletion:     ProcPtr;         {completion routine}
  11438.           ioResult:         OsErr;           {result code}
  11439.           ioNamePtr:        StringPtr;       {used only for dspOpen}
  11440.           ioVRefNum:        Integer;         {volume reference number}
  11441.           ioCRefNum:        Integer;         {driver reference number}
  11442.           csCode:           Integer;         {primary command code}
  11443.           qStatus:          LongInt;         {reserved for ADSP}
  11444.           ccbRefNum:        Integer;         {CCB reference number}
  11445.  
  11446.           CASE Integer OF
  11447.           dspInit,
  11448.           dspCLInit:
  11449.           (
  11450.              ccbPtr:        TPCCB;           {pointer to CCB}
  11451.              userRoutine:   ProcPtr;         {pointer to user routine}
  11452.              sendQSize:     Integer;         {size of send queue}
  11453.              sendQueue:     Ptr;             {pointer to send queue}
  11454.              recvQSize:     Integer;         {size of receive queue}
  11455.              recvQueue:     Ptr;             {pointer to receive queue}
  11456.              attnPtr:       Ptr;             {pointer to attention- }
  11457.                                              { message buffer}
  11458.              localSocket:   Byte;            {local socket number}
  11459.              filler1:       Byte;            {filler for proper alignment}
  11460.            );
  11461.  
  11462.            dspOpen,
  11463.            dspCLListen,
  11464.            dspCLDeny:
  11465.           (
  11466.              localCID:       Integer;        {local connection ID}
  11467.              remoteCID:      Integer;        {remote connection ID}
  11468.              remoteAddress:  AddrBlock;      {remote internet address}
  11469.              filterAddress:  AddrBlock;      {address filter}
  11470.              sendSeq:        LongInt;        {send sequence number}
  11471.              sendWindow:     Integer;        {size of remote buffer}
  11472.              recvSeq:        LongInt;        {receive sequence number}
  11473.              attnSendSeq:    LongInt;        {attention send seq number}
  11474.              attnRecvSeq:    LongInt;        {attention receive seq num}
  11475.              ocMode:         Byte;           {connection opening mode}
  11476.              ocInterval:     Byte;           {interval bet open requests}
  11477.              ocMaximum:      Byte;           {retries of open conn req}
  11478.              filler2:        Byte;           {filler for proper alignment}
  11479.            );
  11480.  
  11481.            dspClose,
  11482.            dspRemove:
  11483.           (
  11484.              abort:          Byte;           {abort send requests}
  11485.              filler3:        Byte;           {filler for proper alignment}
  11486.           );
  11487.  
  11488.           dspStatus:
  11489.           (
  11490.              statusCCB:      TPCCB;          {pointer to CCB}
  11491.              sendQPending:   Integer;        {bytes waiting in send queue}
  11492.              sendQFree:      Integer;        {available send-queue buffer}
  11493.              recvQPending:   Integer;        {bytes in receive queue}
  11494.              recvQFree:      Integer;        {avail receive-queue buffer}
  11495.           )
  11496.  
  11497.           dspRead,
  11498.           dspWrite:
  11499.           (
  11500.              reqCount:       Integer;        {requested number of bytes}
  11501.              actCount:       Integer;        {actual number of bytes}
  11502.              dataPtr:        Ptr;            {pointer to data buffer}
  11503.              eom:            Byte;           {1 if end of message}
  11504.              flush:          Byte;           {1 to send data now}
  11505.           )
  11506.   
  11507.           dspAttention:
  11508.           (
  11509.              attnCode:       Integer;         {client attention code}
  11510.              attnSize:       Integer;         {size of attention data}
  11511.              attnData        Ptr;             {pointer to attention data}
  11512.              attnInterval:   Byte;            {reserved}
  11513.              filler4:        Byte;            {filler for proper alignment}
  11514.           )
  11515.   
  11516.           dspOptions:
  11517.           (
  11518.              sendBlocking:   Integer;          {send-blocking threshold}
  11519.              sendTimer:      Byte;             {reserved}
  11520.              rtmtTimer:      Byte;             {reserved}
  11521.              badSeqMax:      Byte;             {retransmit advice threshold}
  11522.              useCheckSum:    Byte;             {DDP checksum for packets}
  11523.           )
  11524.   
  11525.           dspNewCID:
  11526.           (
  11527.              newCID:          Integer;          {new connection ID}
  11528.           )
  11529.        END;
  11530.  
  11531. The qLink, qType, ioTrap, ioCmdAddr, ioNamePtr, and ioVRefNum fields are filled
  11532. in by the Device Manager; your application should not have to set or read these
  11533. fields. The ioResult field returns the result of the function. If you call the
  11534. routine asynchronously, the Device Manager sets this field to 1 as soon as you
  11535. call the routine and it changes the field to the actual result code when the
  11536. routine completes execution. The ioCompletion field is a pointer to a completion
  11537. routine that you can provide; the Device Manager calls your completion routine
  11538. when it completes execution of the PBControl function. If you are not providing
  11539. a completion routine, specify NIL for this field. 
  11540.  
  11541. The ioCRefNum field is returned by the OpenDriver function. You must specify
  11542. this number every time you call the .DSP driver. 
  11543.  
  11544. The csCode field specifies the command to be executed. You must fill in this
  11545. field before calling the PBControl function. You can use the following constants
  11546. as values for the csCode field: 
  11547.  
  11548. CONST  {ADSP routine selectors}
  11549.        dspInit       = 255;        {create a new connection end}
  11550.        dspRemove     = 254;        {remove a connection end}
  11551.        dspOpen       = 253;        {open a connection}
  11552.        dspClose      = 252;        {close a connection}
  11553.        dspCLInit     = 251;        {create a connection listener}
  11554.        dspCLRemove   = 250;        {remove a connection listener}
  11555.        dspCLListen   = 249;        {post a listener request}
  11556.        dspCLDeny     = 248;        {deny an open-connection request}
  11557.        dspStatus     = 247;        {get status of connection end}
  11558.        dspRead       = 246;        {read data from the connection}
  11559.        dspWrite      = 245;        {write data on the connection}
  11560.        dspAttention  = 244;        {send an attention message}
  11561.        dspOptions    = 243;        {set connection end options}
  11562.        dspReset      = 242;        {forward reset the connection}
  11563.        dspNewCID     = 241;        {generate a cid for a connection end} 
  11564.  
  11565. The qStatus field is reserved for use by ADSP. The ccbRefNum field is the
  11566. reference number of the CCB. The CCB reference number is returned by ADSP in
  11567. response to the dspInit routine. You must specify this number as a parameter to
  11568. every .DSP driver routine you call subsequently.
  11569.  
  11570. The remaining fields are used only for specific routines; each of these fields
  11571. is described in “.DSP Driver Routines” later in this chapter.
  11572.  
  11573. _______________________________________________________________________________
  11574.  
  11575. æKY Opening…and…Maintaining…an…ADSP…Connection
  11576. æC »Opening and Maintaining an ADSP Connection                           AppleTalk Manager
  11577. _______________________________________________________________________________
  11578.  
  11579. To use the AppleTalk Data Stream Protocol (ADSP) to establish and maintain a
  11580. connection between a socket on your local node and a remote socket, use the
  11581. following procedure:
  11582.  
  11583.    1.  Use the MPPOpen function to open the .MPP driver, and then use the
  11584.         OpenDriver function to open the .DSP driver. The OpenDriver function
  11585.         returns the reference number for the .DSP driver. You must supply this
  11586.         reference number each time you call the .DSP driver.
  11587.  
  11588.    2.  Allocate nonrelocatable memory for a connection control block (CCB), send
  11589.         and receive queues, and an attention message buffer. If you need to
  11590.         allocate the
  11591.         memory dynamically while the program is running, use the NewPtr routine.
  11592.         Otherwise, the way in which you allocate the memory depends on the
  11593.         compiler you are using. (Listing 32-4 at the end of this section shows
  11594.         how it’s
  11595.         done in Pascal). The memory that you allocate becomes the property of
  11596.         ADSP
  11597.         when you call the dspInit routine to establish a connection end. You
  11598.         cannot
  11599.         write any data to this memory except by calling ADSP, and you must
  11600.         ensure
  11601.         that the memory remains locked until you call the dspRemove routine to
  11602.         eliminate the connection end.
  11603.  
  11604.         The CCB is 242 bytes. The attention-message buffer must be 570 bytes.
  11605.         When
  11606.          you send bytes to a remote connection end, ADSP stores the bytes in a
  11607.          buffer
  11608.          called the send queue . Until the remote connection end acknowledges
  11609.          their
  11610.          receipt, ADSP keeps the bytes you sent in the send queue so that they
  11611.          are
  11612.          available to be retransmitted if necessary. When the local connection
  11613.          end
  11614.          receives bytes, it stores them in a buffer, called the receive queue,
  11615.          until you
  11616.          read them. The sizes you need for the send and receive queues depend on
  11617.          the
  11618.          lengths of the messages being sent. 
  11619.  
  11620.          ADSP does not transmit data from the remote connection end until there
  11621.          is
  11622.          room for it in your receive queue. If your send or receive queues are
  11623.          too small,
  11624.          they limit the speed with which you can transmit and receive data. A
  11625.          queue
  11626.          size of 600 bytes should work well for most applications. If you are
  11627.          using ADSP
  11628.          to send a continuous flow of data, a larger data buffer improves
  11629.          performance.
  11630.          If your application is sending or receiving the user’s keystrokes, a
  11631.          smaller
  11632.          buffer should be adequate. The constant minDSPQueueSize indicates the
  11633.          minimum queue size that you can use.
  11634.  
  11635.          If you are using a version of the .DSP driver prior to version 1.5, you
  11636.          must
  11637.          allocate send and receive queues that are 12% larger than the actual
  11638.          buffer
  11639.          sizes you need. You must do this in order to provide some extra space
  11640.          for use
  11641.          by the .DSP driver. Version 1.5 and later versions of the .DSP driver
  11642.          use a
  11643.          much smaller, and variable, portion of buffer space for overhead. The
  11644.          .DSP
  11645.          driver version number is stored in the low byte of the qFlags field,
  11646.          which is
  11647.          the first field in the dCtlQHdr field in the driver’s device control
  11648.          entry (DCE)
  11649.          data structure. Version 1.5 of the .DSP driver has a version number of
  11650.          4 in the
  11651.          DCE. The DCE is described in the Device Manager chapters of Volumes II
  11652.          and
  11653.          V.
  11654.  
  11655.    3.  Use the dspInit routine to establish a connection end. You must provide
  11656.         pointers to the CCB, send queue, receive queue, and attention-message
  11657.         buffer.
  11658.         You may also provide a pointer to the user routine that ADSP calls when
  11659.         your
  11660.         connection end receives an unsolicited connection event. User routines
  11661.         are
  11662.         discussed in “Writing a User Routine for Connection Events” later in
  11663.         this
  11664.         chapter.
  11665.  
  11666.          If there is a specific socket that you want to use for the connection
  11667.          end, you can
  11668.          specify the socket number in the localSocket parameter. If you want
  11669.          ADSP to
  11670.          assign the socket for you, specify 0 for the localSocket parameter.
  11671.          ADSP returns
  11672.          the socket number when the dspInit routine completes execution.
  11673.  
  11674.    4.  If you wish, you can use the NBPRegister function to add the name and
  11675.         address of your connection end to the node’s names table. The
  11676.         NBPRegister
  11677.         function is described in the AppleTalk Manager chapter of Volume II. 
  11678.  
  11679.    5.  You can use the dspOptions routine to set several parameters that control
  11680.    the
  11681.         behavior of the connection end. Because every parameter has a default
  11682.         value,
  11683.         the use of the dspOptions routine is optional. You can specify values
  11684.         for the
  11685.         following parameters:
  11686.  
  11687.           •  The sendBlocking parameter, which sets the maximum number of bytes
  11688.                that may accumulate in the send queue before ADSP sends a packet
  11689.                to the
  11690.                remote connection end. You can experiment with different values
  11691.                of the
  11692.                sendBlocking parameter to determine which provides the best
  11693.                performance. Under most circumstances, the default value of
  11694.                16 bytes gives
  11695.                good performance.
  11696.  
  11697.          •  The badSeqMax parameter, which sets the maximum number of
  11698.               out-of-sequence data packets that the local connection end can
  11699.               receive
  11700.               before requesting the remote connection end to retransmit the
  11701.               missing
  11702.               data. Under most circumstances, the default value of 3 provides
  11703.               good
  11704.               performance. 
  11705.  
  11706.          •  The useCheckSum parameter, which determines whether the Datagram
  11707.              Delivery Protocol (DDP) should compute a checksum and include it in
  11708.              each
  11709.              packet that it sends to the remote connection end. Using checksums
  11710.              slows
  11711.              communications slightly. Normally ADSP and DDP perform enough error
  11712.              checking to ensure safe delivery of all data. Set the useCheckSum
  11713.              parameter
  11714.              to 1 only if you feel that the network is highly unreliable.
  11715.  
  11716.    6.  Call the dspOpen routine to open the connection. The dspOpen routine has
  11717.         four possible modes of operation: ocAccept, ocEstablish, ocRequest, and
  11718.         ocPassive. Normally you use either the ocRequest or ocPassive mode. You
  11719.         must specify one of these four modes for the ocMode parameter when you
  11720.         call
  11721.         the dspOpen routine. 
  11722.  
  11723.        The ocAccept mode is used only by connection servers. The ocEstablish
  11724.        mode is
  11725.        used by routines that determine their connection-opening parameters and
  11726.        establish a connection independently of ADSP, but use ADSP to transmit
  11727.        and
  11728.        receive data.
  11729.  
  11730.         Use the ocRequest mode when you want to establish communications with a
  11731.         specific socket on the internet. When you execute the dspOpen routine in
  11732.         the
  11733.         ocRequest mode, ADSP sends an open-connection request to the address you
  11734.         specify. 
  11735.  
  11736.         If the socket to which you send the open-connection request is a
  11737.         connection
  11738.         listener, the connection server that operates that connection listener
  11739.         can
  11740.         choose any socket on the internet to be the connection end that responds
  11741.         to the
  11742.         open-connection request. To restrict the socket from which you will
  11743.         accept a
  11744.         response to your open-connection request, specify a value for the
  11745.         filterAddress
  11746.         parameter to the dspOpen routine. When your connection end receives a
  11747.         response from a socket that meets the restrictions of the filterAddress
  11748.         parameter, it acknowledges the response and ADSP completes the
  11749.         connection. 
  11750.  
  11751.         To use the ocRequest mode, you must know the complete internet address
  11752.         of
  11753.         the remote socket, and the ADSP client at that address must either be a
  11754.         connection listener or have executed the dspOpen routine in the
  11755.         ocPassive
  11756.         mode. You can use the PLookupName function to obtain a list of names of
  11757.         objects on the internet and to determine the internet address of a
  11758.         socket when
  11759.         you know its name. The PLookupName function is the preferred interface
  11760.         version of the NBPLookup function. The NBPLookup function is described
  11761.         in
  11762.         the AppleTalk Manager chapter of Volume II. The preferred interface is
  11763.         described in the AppleTalk Manager chapter of Volume V. Enhancements to
  11764.         the wildcard-lookup feature of the Name-Binding Protocol (NBP) are
  11765.         discussed
  11766.         in “A New NBP Wildcard Character” earlier in this chapter. 
  11767.  
  11768.         Use the ocPassive mode when you expect to receive an open-connection
  11769.         request from a remote socket. You can specify a value for the
  11770.         filterAddress
  11771.         parameter to restrict the network number, node ID, or socket number from
  11772.         which you will accept an open-connection request. When your connection
  11773.         end
  11774.          receives an open-connection request that meets the restrictions of the
  11775.         filterAddress parameter, it acknowledges the request and ADSP completes
  11776.         the
  11777.         connection. 
  11778.  
  11779.         You can poll the state field in the CCB to determine when the connection
  11780.         end
  11781.         is waiting to receive an open-connection request, when the connection
  11782.         end is
  11783.         waiting to receive an acknowledgment of an open-connection request, and
  11784.         when the connection is open. (The CCB is described in “The ADSP
  11785.         Connection
  11786.         Control Block” earlier in this chapter.) Alternatively, you can check
  11787.         the result
  11788.         code for the dspOpen routine when the routine completes execution. If
  11789.         the
  11790.         routine returns the noErr result code, then the connection is open.
  11791.  
  11792.    7.   Use the dspRead routine to read data that your connection end has
  11793.    received
  11794.          from the remote connection end. Use the dspWrite routine to send data
  11795.          to the
  11796.          remote connection end. Use the dspAttention routine to send attention
  11797.          messages to the remote connection end.
  11798.  
  11799.          The dspWrite routine places data in the send queue. ADSP is a
  11800.          full-duplex,
  11801.          symmetric communications protocol. You can send data at any time, and
  11802.          your
  11803.          connection end can receive data at any time, even at the same time as
  11804.          you are
  11805.          sending data. ADSP transmits the data in the send queue when one of the
  11806.          following conditions occurs:
  11807.  
  11808.            •  You call the dspWrite routine with the flush parameter set to a
  11809.            nonzero
  11810.                number.
  11811.  
  11812.            •  The number of bytes in the send queue equals or exceeds the
  11813.            blocking
  11814.                factor that you set with the dspOptions routine.
  11815.  
  11816.             •  The send timer expires. The send timer sets the maximum amount of
  11817.                  time that can pass before ADSP sends all unsent data in the
  11818.                  send queue to
  11819.                  the remote connection end. ADSP calculates the best value to
  11820.                  use for this
  11821.                  timer and sets it automatically.
  11822.  
  11823.             •  A connection event requires that the local connection end send an
  11824.                 acknowledgment packet to the remote connection end.
  11825.  
  11826.           If you send more data to the send queue than it can hold, the dspWrite
  11827.  
  11828.           routine does not complete execution until it has written all the data
  11829.           to the
  11830.           send queue. If you execute the dspWrite routine asynchronously, ADSP 
  11831.           returns control to your program and writes the data to the send queue
  11832.           as
  11833.           quickly as it can. This technique provides the most efficient use of
  11834.           the send
  11835.           queue by your program and by ADSP. Because ADSP does not remove data
  11836.           from the send queue until that data has not only been sent but also
  11837.           acknowledged by the remote connection end, using the flush parameter
  11838.           to the
  11839.           dspWrite routine does not guarantee that the send queue is empty. You
  11840.           can
  11841.           use the dspStatus routine to determine how much free buffer space is
  11842.           available in the send queue. 
  11843.  
  11844.          The dspRead routine reads data from the receive queue into your
  11845.          application’s
  11846.           private data buffer. ADSP does not transmit data until there is space
  11847.           available
  11848.           in the other end’s receive queue to accept it. Because a full receive
  11849.           queue
  11850.           slows the communications rate, you should read data from the receive
  11851.           queue
  11852.           as often as necessary to keep sufficient buffer space available for
  11853.           new data. You
  11854.           can use either of two techniques to do this:
  11855.  
  11856.             •  Allocate a small receive queue (about 600 bytes) and call the
  11857.             dspRead
  11858.                 routine asynchronously. Your completion routine for the dspRead
  11859.                 routine
  11860.                 should then call the dspRead routine again.
  11861.  
  11862.             •  Allocate a large receive queue and call the dspRead routine less
  11863.             frequently.
  11864.  
  11865.            If there is less data in the receive queue than the amount you
  11866.            specify with the
  11867.            reqCount parameter to the dspRead command, the command does not
  11868.            complete execution until there is enough data available to satisfy
  11869.            the request.
  11870.            There are three exceptions to this rule: 
  11871.  
  11872.              •  If the end-of-message bit in the ADSP packet header is set, the
  11873.              dspRead
  11874.                  command reads the data in the receive queue, returns the actual
  11875.                  amount
  11876.                  of data read in the actCount parameter, and returns the eom
  11877.                  parameter set
  11878.                  to 1. 
  11879.  
  11880.              •  If you have closed the connection end before calling the dspRead
  11881.              routine
  11882.                   (that is, the connection is half open), the command reads
  11883.                   whatever data
  11884.                   is available and returns the actual amount of data read in the
  11885.                   actCount
  11886.                  parameter. 
  11887.  
  11888.              •  If ADSP has closed the connection before you call the dspRead
  11889.              routine
  11890.                   and there is no data in the receive queue, the routine returns
  11891.                   the noErr
  11892.                   result code with the actCount parameter set to 0 and the eom
  11893.                   parameter
  11894.                   set to 0.
  11895.  
  11896.            In addition to the byte-stream data format implemented by the dspRead
  11897.            and
  11898.            dspWrite routines, ADSP provides a mechanism for sending and
  11899.            receiving
  11900.            control signals or information separate from the byte stream. You use
  11901.            the
  11902.            dspAttention routine to send an attention code and an attention
  11903.            message to
  11904.            the remote connection end. When your connection end receives an
  11905.            attention
  11906.            message, ADSP’s interrupt handler sets the eAttention flag in the
  11907.            userFlags
  11908.            field of the CCB and calls your user routine. Your user routine must
  11909.            first
  11910.            clear the userFlags field. Then your routine can read the attention
  11911.            code and
  11912.            attention message and take whatever action you deem appropriate. 
  11913.  
  11914.           Because ADSP is often used by terminal emulation programs and other
  11915.           applications that pass the data they receive on to the user without
  11916.           processing
  11917.           it, attention messages provide a mechanism for the applications that
  11918.           are
  11919.           clients of the connection ends to communicate with each other. For
  11920.           example,
  11921.           you could use attention messages to implement a handshaking and
  11922.           data-checking protocol for a program that transfers disk files between
  11923.           two
  11924.           applications, neither one of which is a file server. Or a database
  11925.           server on a
  11926.           mainframe computer that uses ADSP to communicate with Macintosh
  11927.           computer workstations could use the attention mechanism to inform the
  11928.           workstations when the database is about to be closed down for
  11929.           maintenance.
  11930.  
  11931.    8.  When you are ready to close the ADSP connection, you can use the dspClose
  11932.    or
  11933.         dspRemove routines to close the connection end. Use the dspClose routine
  11934.         if
  11935.         you intend to use that connection end to open another connection and do
  11936.         not
  11937.         want to release the memory you allocated for the connection end. Use the
  11938.         dspRemove routine if you are completely finished with the connection end
  11939.         and want to release the memory.
  11940.  
  11941.         You can continue to read data from the receive queue after you have
  11942.         called the
  11943.         dspClose routine, but not after you have called the dspRemove routine.
  11944.         You
  11945.         can use the dspStatus routine to determine whether any data is remaining
  11946.         in
  11947.         the receive queue, or you can read data from the receive queue until
  11948.         both the
  11949.         actCount and eom fields of the dspRead parameter block return 0.
  11950.  
  11951.        If you set the abort parameter for the dspClose or dspRemove routines to
  11952.        0,
  11953.        then ADSP does not close the connection or the connection end until it
  11954.        has
  11955.        sent—and received acknowledgment for—all data in the send queue and any
  11956.        pending attention messages. If you set the abort parameter to 1, then
  11957.        ADSP
  11958.        discards any data in the send queue and any attention messages that have
  11959.        not
  11960.        already been sent.
  11961.  
  11962.         After you have executed the dspRemove routine, you can release the
  11963.         memory
  11964.         you allocated for the CCB and data buffers.
  11965.  
  11966. Listing 32-4 illustrates the use of ADSP. This routine opens the .MPP and .DSP
  11967. drivers and allocates memory for its internal data buffers, for the CCB, and for
  11968. the send, receive, and attention-message buffers. Then the routine uses the
  11969. dspInit routine to establish a connection end and uses NBP to register the name
  11970. of the connection end on the internet. (The user routine specified by the
  11971. userRoutine parameter to the dspInit function is shown in Listing 326.) Next,
  11972. Listing 32-4 uses the dspOptions routine to set the blocking factor to 24 bytes.
  11973. The routine uses NBP to determine the address of a socket whose name was chosen
  11974. by the user and sends an open-connection request (dspOpen) to that socket. When
  11975. the dspOpen routine completes execution, the routine sends data and an attention
  11976. message to the remote connection end and reads data from its receive queue.
  11977. Finally, the routine closes the connection end with the dspRemove routine and
  11978. releases the memory it allocated.  
  11979.  
  11980. ¿ Listing 32-4   Using ADSP to establish and use a connection
  11981.  
  11982. PROCEDURE MyADSP;
  11983.  
  11984. CONST
  11985.    qSize=  600;         {queue space}
  11986.    myDataSize=  128;    {size of internal read/write buffers}
  11987.    blockFact=  24;      {blocking factor}
  11988. TYPE  
  11989. {modify the connection control block to add storage for A5}
  11990.    myTRCCB = RECORD
  11991.       myA5: longint;
  11992.       u: TRCCB;
  11993.    END;
  11994. VAR
  11995.    dspSendQPtr:      Ptr;
  11996.    dspRecvQPtr:      Ptr;
  11997.    dspAttnBufPtr:    Ptr;
  11998.    myData2ReadPtr:   Ptr;
  11999.    myData2WritePtr:  Ptr;
  12000.    myAttnMsgPtr:     Ptr;
  12001.    dspCCB:           myTRCCB;
  12002.    myDSPPBPtr:       DSPPBPtr;
  12003.    myMPPPBPtr:       MPPPBPtr;
  12004.    myNTEName:        NamesTableEntry;
  12005.    myAddrBlk:        AddrBlock;
  12006.    drvrRefNum:       Integer;
  12007.    mppRefNum:        Integer;
  12008.    connRefNum:       Integer;
  12009.    gReceivedAnEvent: Boolean;
  12010.    myAttnCode:       Integer;
  12011.    tempFlag:         Byte;
  12012.    tempCFlag:        Integer;
  12013.    myErr:            OSErr;  
  12014.  
  12015. BEGIN 
  12016.    myErr := OpenDriver('.MPP', mppRefNum);    {open .MPP driver}
  12017.    IF myErr <> noErr THEN DoErr(myErr);       {check and handle error}
  12018.    myErr := OpenDriver('.DSP', drvrRefNum);   {open .DSP driver}
  12019.    IF myErr <> noErr THEN DoErr(myErr);       {check and handle error}
  12020.   
  12021.    {allocate memory for data buffers}
  12022.    dspSendQPtr := NewPtr(qSize);              {ADSP use only}
  12023.    dspRecvQPtr := NewPtr(qSize);              {ADSP use only}
  12024.    dspAttnBufPtr := NewPtr(attnBufSize);      {ADSP use only}
  12025.    myData2ReadPtr := NewPtr(myDataSize);
  12026.    myData2WritePtr := NewPtr(myDataSize);
  12027.    myAttnMsgPtr := NewPtr(myDataSize);
  12028.    myDSPPBPtr := DSPPBPtr(NewPtr(SizeOf(DSPParamBlock)));
  12029.    myMPPPBPtr := MPPPBPtr(NewPtr(SizeOf(MPPParamBlock)));
  12030.   
  12031.    WITH myDSPPBPtr^ DO       {set up dspInit parameters}
  12032.    BEGIN
  12033.       ioCRefNum := drvrRefNum;     {ADSP driver ref num}
  12034.       csCode := dspInit;
  12035.       ccbPtr := @dspCCB;           {pointer to CCB}
  12036.       userRoutine := @myConnectionEvtUserRoutine;
  12037.                                    {see Listing 32-6}
  12038.       sendQSize := qSize;          {size of send queue}
  12039.       sendQueue := dspSendQPtr;    {send-queue buffer}
  12040.       recvQSize := qSize;          {size of receive queue}
  12041.       recvQueue := dspRecvQPtr;    {receive-queue buffer}
  12042.       attnPtr := dspAttnBufPtr;    {receive-attention buffer}
  12043.       localSocket := 0;            {let ADSP assign socket}
  12044.    END;
  12045.  
  12046.    gReceivedAnEvent := FALSE;
  12047.    dspCCB.myA5 := SetCurrentA5;    {save A5 for the user routine}
  12048.    {establish a connection end}
  12049.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12050.    IF myErr <> noErr THEN DoErr(myErr);  {check and handle error}
  12051.    connRefNum := myDSPPBPtr^.ccbRefNum;  {save CCB ref num for later}
  12052.  
  12053.    NBPSetNTE(@myNTEName, 'The Object', 'The Type',
  12054.      '*', myDSPPBPtr^.localSocket);  
  12055.                                          {set up NBP names table entry}
  12056.    WITH myMPPPBPtr^ DO                   {set up PRegisterName }
  12057.                                          { parameters}
  12058.    BEGIN
  12059.       interval := 7;                     {retransmit every 7*8=56 ticks}
  12060.       count := 3;                        {and retry 3 times}
  12061.       entityPtr := @myNTEName;           {name to register}
  12062.       verifyFlag :=   0;                 {don't verify this name}
  12063.    END;
  12064.    {register this socket}
  12065.    myErr := PRegisterName(myMPPPBPtr, FALSE);  
  12066.                                          {register this socket}
  12067.    IF myErr <> noErr THEN DoErr(myErr);  {check and handle error}
  12068.  
  12069.    WITH myDSPPBPtr^ DO                   {set up dspOptions parameters}
  12070.    BEGIN
  12071.       ioCRefNum := drvrRefNum;           {ADSP driver ref num}
  12072.       csCode := dspOptions;
  12073.       ccbRefNum := connRefNum;           {connection ref num}
  12074.       sendBlocking := blockFact;         {quantum for data packet}
  12075.       badSeqMax :=   0:                  {use default}
  12076.       useCheckSum :=   0;                {don't calculate checksum}
  12077.    END;
  12078.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12079.                                          {set options}
  12080.    IF myErr <> noErr THEN DoErr(myErr);  {check and handle error}
  12081.  
  12082.    PickASocket(myAddrBlk);
  12083.       {routine using the PLookupName function to pick a socket }
  12084.       { that will be used to establish an open connection}
  12085.  
  12086.    {open a connection with the chosen socket}
  12087.    WITH myDSPPBPtr^ DO                    {set up dspOpen parameters}
  12088.    BEGIN
  12089.       ioCRefNum := drvrRefNum;            {ADSP driver ref num}
  12090.       csCode := dspOpen;
  12091.       ccbRefNum := connRefNum;            {connection ref num}
  12092.       remoteAddress := myAddrBlk;         {address of remote socket }
  12093.                                           { from PLookupName function}
  12094.       filterAddress := myAddrBlk;         {address filter, specified }
  12095.                                           { socket address only}
  12096.       ocMode := ocRequest;                {open connection mode}
  12097.       ocInterval := 0;                    {use default retry interval}
  12098.       ocMaximum := 0;                     {use default retry maximum}
  12099.    END;
  12100.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12101.                                           {open a connection}
  12102.    IF myErr <> noErr THEN DoErr(myErr);   {check and handle error}
  12103.  
  12104.    {the connection with the chosen socket is open, so now send to }
  12105.    { the send queue exactly myDataSize number of bytes}
  12106.    WITH myDSPPBPtr^ DO                    {set up dspWrite parameters}
  12107.    BEGIN       
  12108.       ioCRefNum := drvrRefNum;            {ADSP driver ref num}
  12109.       csCode := dspWrite;
  12110.       ccbRefNum := connRefNum;            {connection ref num}
  12111.       reqCount := myDataSize;             {write this number of bytes}
  12112.       dataPtr := myData2WritePtr;         {pointer to send queue}
  12113.       eom := 1;                           {1 means last byte is logical }
  12114.                                           { end-of-message}
  12115.       flush := 1;                         {1 means send data now}
  12116.    END;
  12117.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12118.                                           {send data to the remote }
  12119.                                           { connection}
  12120.    IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
  12121.  
  12122.    {now send an attention message to the remote connection end}
  12123.    WITH myDSPPBPtr^ DO                    {set up dspAttention parameters}
  12124.    BEGIN
  12125.       ioCRefNum := drvrRefNum;            {ADSP driver ref num}
  12126.       csCode := dspAttention;
  12127.       ccbRefNum := connRefNum;            {connection ref num}
  12128.       attnCode := 0;                      {user-defined attention code}
  12129.       attnSize := myDataSize;             {length of attention message}
  12130.       attnData := myAttnMsgPtr;           {attention message}
  12131.    END;
  12132.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12133.    IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
  12134.  
  12135.    {Now read from the receive queue exactly myDataSize number }
  12136.    { of bytes.}
  12137.    WITH myDSPPBPtr^ DO                    {set up dspRead parameters}
  12138.    BEGIN 
  12139.       ioCRefNum := drvrRefNum;            {ADSP driver ref num}
  12140.       csCode := dspRead;
  12141.       ccbRefNum := connRefNum;            {connection ref num}
  12142.       reqCount := myDataSize;             {read this number of bytes}
  12143.       dataPtr := myData2ReadPtr;          {pointer to read buffer}
  12144.    END;
  12145.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12146.                                           {read data from the remote }
  12147.                                           { connection}
  12148.    IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
  12149.  
  12150.    {we're done with the connection, so remove it}
  12151.    WITH myDSPPBPtr^ DO                    {set up dspRemove parameters}
  12152.    BEGIN
  12153.       ioCRefNum := drvrRefNum;            {ADSP driver ref num}
  12154.       csCode := dspRemove;
  12155.       ccbRefNum := connRefNum;            {connection ref num}
  12156.       abort := 0;                         {don't close until everything }
  12157.                                           { is sent and received}
  12158.    END;
  12159.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12160.                                           {close and remove the connection}
  12161.    IF myErr <> noErr THEN DOErr(myErr);{check and handle error}
  12162.  
  12163.    {we're done with this connection, so give back the memory}
  12164.    DisposPtr(dspSendQPtr);
  12165.    DisposPtr(dspRecvQPtr);
  12166.    DisposPtr(dspAttnBufPtr);
  12167.    DisposPtr(myData2ReadPtr);
  12168.    DisposPtr(myData2WritePtr);
  12169.    DisposPtr(myAttnMsgPtr);
  12170.    DisposPtr(Ptr(myDSPPBPtr));
  12171.    DisposPtr(Ptr(myMPPPBPtr));
  12172.  
  12173. END;      {MyADSP}
  12174. _______________________________________________________________________________
  12175.  
  12176. æKY Creating…and…Using…a…Connection…Listener
  12177. æC »Creating and Using a Connection Listener                             AppleTalk Manager
  12178. _______________________________________________________________________________
  12179.  
  12180. A connection listener is a special sort of AppleTalk Data Stream Protocol (ADSP)
  12181. connection end that cannot receive or transmit data streams or attention
  12182. messages. The sole function of a connection listener is to wait passively to
  12183. receive an open-connection request and to inform its client, the connection
  12184. server, when it receives one. The connection server can then accept or deny the
  12185. open-connection request. If it accepts the request, the connection server
  12186. selects a socket to use as a connection end, establishes a connection end on
  12187. that socket, and sends an acknowledgment and connection request back to the
  12188. requesting connection end. The connection server can use the same socket as it
  12189. used for the connection listener or can select a different socket as the
  12190. connection end.
  12191.  
  12192. Use the following procedure to establish a connection listener and to use that
  12193. connection listener to open a connection with a remote connection end:
  12194.  
  12195.    1.  Use the MPPOpen function to open the .MPP driver and then use the
  12196.         OpenDriver function to open the .DSP driver. The OpenDriver function
  12197.         returns the reference number for the .DSP driver. You must supply this
  12198.         reference number each time you call the .DSP driver.
  12199.  
  12200.    2.  Allocate nonrelocatable memory for a connection control block (CCB). (The
  12201.         CCB is described in “The ADSP Connection Control Block” earlier in this
  12202.         chapter.) A connection listener does not need send and receive queues or
  12203.         an
  12204.         attention-message buffer. The memory that you allocate becomes the
  12205.         property
  12206.         of ADSP when you call the dspCLInit routine to establish a connection
  12207.         listener.
  12208.         You cannot write any data to this memory except by calling ADSP, and you
  12209.         must ensure that the memory remains locked until you call the dspRemove
  12210.         routine to eliminate the connection end. The CCB is 242 bytes. 
  12211.  
  12212.    3.  Call the dspCLInit routine to establish a connection listener. You must
  12213.    provide
  12214.         a pointer to the CCB. 
  12215.  
  12216.        If there is a specific socket that you want to use for the connection
  12217.        listener, you
  12218.        can specify the socket number in the localSocket parameter. If you want
  12219.        ADSP
  12220.        to assign the socket for you, specify 0 for the localSocket parameter.
  12221.        ADSP
  12222.        returns the socket number when the dspCLInit routine completes execution.
  12223.  
  12224.    4.  If you wish, you can use the NBPRegister function to add the name and
  12225.         address of your connection listener to the node’s names table. The
  12226.         NBPRegister function is described in the AppleTalk Manager chapter of
  12227.         Volume II.
  12228.  
  12229.    5.  Use the dspCLListen routine to cause the connection listener to wait for
  12230.    an
  12231.         open-connection request. Because the dspCLListen routine does not
  12232.         complete
  12233.         execution until it receives a connection request, you should call this
  12234.         routine
  12235.         asynchronously. You can specify a value for the filterAddress parameter
  12236.         to
  12237.         restrict the network number, node ID, or socket number from which you
  12238.         will
  12239.         accept an open-connection request. 
  12240.  
  12241.         When the dspCLListen routine receives an open-connection request that
  12242.         meets the restrictions of the filterAddress parameter, it returns a
  12243.         noErr result
  12244.         code (if you executed the routine asynchronously, it places a noErr
  12245.         result code
  12246.         in the ioResult parameter) and places values in the parameter block for
  12247.         the
  12248.         remoteCID, remoteAddress, sendSeq, sendWindow, and attnSendSeq
  12249.         parameters. 
  12250.  
  12251.    6.  If you want to open the connection, call the dspInit routine to establish
  12252.    a
  12253.         connection end. You can use any available socket on the node for the
  12254.         connection end, including the socket that you used for the connection
  12255.         listener.
  12256.         Because a single socket can have more than one CCB connected with it,
  12257.         the
  12258.         socket can function simultaneously as a connection end and a connection
  12259.         listener. 
  12260.  
  12261.         You can check the address of the remote socket to determine if it meets
  12262.         your
  12263.         criteria for a connection end. Although the filterAddress parameter to
  12264.         the
  12265.         dspCLListen routine provides some screening of socket addresses, it
  12266.         cannot
  12267.         check for network number ranges, for example, or for a specific set of
  12268.         socket
  12269.         numbers. If for some reason you want to deny the connection request,
  12270.         call the
  12271.         dspDeny routine, specifying the CCB of the connection listener in the
  12272.         ccbRefNum parameter. Because the dspCLListen routine completes execution
  12273.         when it receives an open-connection request, you must return to step 5
  12274.         to wait
  12275.         for another connection request.
  12276.  
  12277.    7.  Call the dspOpen routine to open the connection. Specify the value
  12278.    ocAccept
  12279.         for the ocMode parameter and specify in the ccbRefNum parameter the
  12280.         reference number of the CCB for the connection end that you want to use.
  12281.         When you call the dspOpen routine, you must provide the values returned
  12282.         by
  12283.         the dspCLListen routine for the remoteCID, remoteAddress, sendSeq,
  12284.         sendWindow, and attnSendSeq parameters.
  12285.  
  12286.         You can poll the state field in the CCB to determine when the connection
  12287.         is
  12288.         open. Alternatively, you can check the result code for the dspOpen
  12289.         routine
  12290.         when the routine completes execution. If the routine returns the noErr
  12291.         result
  12292.         code, then the connection is open.
  12293.  
  12294.     8.  You can now send and receive data and attention messages over the
  12295.          connection, as described in the preceding section, “Opening and
  12296.          Maintaining
  12297.          an ADSP Connection.” When you are ready to close the connection, you
  12298.          can
  12299.          use the dspClose or dspRemove routines, which are also described in the
  12300.          preceding section.
  12301.  
  12302.    9.  When you are finished using the connection listener, you can use the
  12303.         dspCLRemove routine to eliminate it. Once you have called the
  12304.         dspCLRemove routine, you can release the memory you allocated for the
  12305.         connection listener’s CCB.
  12306.  
  12307. Listing 32-5 illustrates the use of ADSP to establish and use a connection
  12308. listener. It opens the .MPP and .DSP drivers and allocates memory for the CCB.
  12309. Then it uses the dspCLInit routine to establish a connection listener, uses the
  12310. Name-Binding Protocol (NBP) to register the name of the connection end on the
  12311. internet, and uses the dspCLListen routine to wait for a connection request.
  12312. When the routine receives a connection request, it calls the dspOpen routine to
  12313. complete the connection.
  12314.  
  12315. ¿ Listing 32-5   Using ADSP to establish and use a connection listener
  12316.  
  12317. VAR
  12318.    dspCCBPtr:     TPCCB;
  12319.    myDSPPBPtr:    DSPPBPtr;
  12320.    myMPPPBPtr:    MPPPBPtr;
  12321.    myNTEName:     NamesTableEntry;
  12322.    drvrRefNum:    Integer;
  12323.    mppRefNum:     Integer;
  12324.    connRefNum:    Integer;
  12325.    myErr:         OSErr;
  12326.  
  12327. BEGIN 
  12328.    myErr := OpenDriver('.MPP', mppRefNum);   { open .MPP driver }
  12329.    IF myErr <> noErr THEN DoErr(myErr);      {check and handle error}
  12330.    myErr := OpenDriver('.DSP', drvrRefNum);  {open .DSP driver}
  12331.    IF myErr <> noErr THEN DoErr(myErr);      {check and handle error}
  12332.  
  12333.    {allocate memory for data buffers}
  12334.    dspCCBPtr := TPCCB(NewPtr(SizeOf(TRCCB)));
  12335.    myDSPPBPtr := DSPPBPtr(NewPtr(SizeOf(DSPParamBlock)));
  12336.    myMPPPBPtr := MPPPBPtr(NewPtr(SizeOf(MPPParamBlock)));
  12337.  
  12338.    WITH myDSPPBPtr^ DO                     {set up dspCLInit parameters}
  12339.    BEGIN
  12340.       ioCRefNum := drvrRefNum;             {ADSP driver ref num}
  12341.       csCode := dspCLInit;
  12342.       ccbPtr := dspCCBPtr;                 {pointer to CCB}
  12343.       localSocket := 0;                    {local socket number}
  12344.    END;
  12345.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12346.                                            {establish a connection listener}
  12347.  
  12348.    IF myErr <> noErr THEN DoErr(myErr);    {check and handle error}
  12349.    connRefNum := myDSPPBPtr^.ccbRefNum;    {save CCB ref num for later}
  12350.  
  12351.    NBPSetNTE(@myNTEName, 'The Object', 'The Type',
  12352.              '*', myDSPPBPtr^.localSocket);  
  12353.                                            {set up NBP names table entry}
  12354.    WITH myMPPPBPtr^ DO                     {set up PRegisterName parameters}
  12355.    BEGIN
  12356.       interval := 7;                       {retransmit every 7*8=56 ticks}
  12357.       count := 3;                          {and retry 3 times}
  12358.       entityPtr := @myNTEname;             {name to register}
  12359.       verifyFlag := 0;                     {don't verify this name}
  12360.    END;
  12361.    myErr := PRegisterName(myMPPPBPtr, FALSE);
  12362.                                            {register this name}
  12363.    IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
  12364.  
  12365.    WITH myDSPPBPtr^ DO                     {set up dspCLListen parameters}
  12366.    BEGIN
  12367.       ioCRefNum := drvrRefNum;             {ADSP driver ref num}
  12368.       csCode := dspCLListen;
  12369.       ccbRefNum := connRefNum;             {connection ref num}
  12370.       filterAddress := AddrBlock(0);       {connect with anybody}
  12371.    END;
  12372.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), TRUE);
  12373.                                            {listen for connection requests}
  12374.    WHILE myDSPPBPtr^.ioResult = 1 DO
  12375.    BEGIN
  12376.       {return control to user while waiting for }
  12377.       { a connection request}
  12378.       GoDoSomething;
  12379.    END;
  12380.    IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
  12381.  
  12382.    {You received a connection request; now open a connection }
  12383.    { The dspCLListen call has returned values into the }
  12384.    { remoteCID, remoteAddress, sendSeq, sendWindow, }
  12385.    { and attnSendSeq fields of the parameter block.}
  12386.  
  12387.    WITH myDSPPBPtr^ DO                      {set up dspOpen parameters}
  12388.    BEGIN
  12389.       ioCRefNum := drvrRefNum;              {ADSP driver ref num}
  12390.       csCode := dspOpen;
  12391.       ccbRefNum := connRefNum;              {connection ref num}
  12392.       ocMode := ocAccept;                   {open connection mode}
  12393.       ocInterval := 0;                      {use default retry interval}
  12394.       ocMaximum := 0;                       {use default retry maximum}
  12395.    END;
  12396.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE); 
  12397.                                             {open a connection}
  12398.    IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
  12399.  
  12400.  
  12401.    {Listing 32-4 shows how to use ADSP to maintain a connection.}
  12402.   
  12403. END;      {MyCLADSP}
  12404.  
  12405. _______________________________________________________________________________
  12406.  
  12407. æKY Writing…a…User…Routine…for…Connection…Events
  12408. æC »Writing a User Routine for Connection Events                         AppleTalk Manager
  12409. _______________________________________________________________________________
  12410.  
  12411. When you execute the dspInit routine, you can specify a pointer to a routine
  12412. that you provide (referred to as the user routine ). Whenever an unsolicited
  12413. connection event occurs, the AppleTalk Data Stream Protocol (ADSP) sets a flag
  12414. in the connection control block (CCB) and calls the user routine. The user
  12415. routine must clear the flag to acknowledge that it has read the flag field, and
  12416. then can respond to the event in any manner you deem appropriate. The CCB flags
  12417. are described in “The ADSP Connection Control Block” earlier in this chapter.
  12418. The four following types of unsolicited connection events set flags in the CCB:
  12419.  
  12420.   •  ADSP has been informed by the remote connection end that the remote
  12421.       connection end is about to close the connection. An appropriate reponse
  12422.       might
  12423.       be to store a flag indicating that the connection end is about to close.
  12424.       When your
  12425.       application regains control, it can then display a dialog box informing
  12426.       the user
  12427.       of this event and asking whether the application should attempt to
  12428.       reconnect
  12429.       later.  
  12430.  
  12431.   •  ADSP has determined that the remote connection end is not responding and so
  12432.       has closed the connection. Your user routine can attempt to open a new
  12433.       connection immediately. Alternatively, you can store a flag indicating
  12434.       that the
  12435.       connection has closed, and when your application regains control, it can
  12436.       display
  12437.       a dialog box asking the user whether to attempt to reconnect. 
  12438.  
  12439.   •  ADSP has received an attention message from the remote connection end.
  12440.       Depending on what you are using the attention-message mechanism for, you
  12441.       might want to read the attention code in the attnCode field of the CCB and
  12442.       the
  12443.       attention message pointed to by the attnPtr field of the CCB. 
  12444.  
  12445.   •  ADSP has received a forward reset command from the remote client end, has
  12446.       discarded all ADSP data not yet delivered, including the data in the
  12447.       receive
  12448.       queue of the local client end, and has resynchronized the connection. Your
  12449.       response to this event depends on the purpose for which you are using the
  12450.       forward reset mechanism. You might want to resend the last data you have
  12451.       sent
  12452.       or inform the user of the event. 
  12453.  
  12454. When ADSP calls your user routine, the CPU is in interrupt-processing mode and
  12455. register A1 contains a pointer to the CCB of the connection end that generated
  12456. the event. You can examine the userFlags field of the CCB to determine what
  12457. event caused the interrupt, and you can examine the state field of the CCB to
  12458. determine the current state of the connection. 
  12459.  
  12460. Because the CPU is set to interrupt-processing mode, your user routine must
  12461. preserve all registers other than A0, A1, D0, D1, and D2. Your routine must not
  12462. make any direct or indirect calls to the Memory Manager and can’t depend on
  12463. handles to unlocked blocks being valid. If you want to use any of your
  12464. application’s global variables, you must save the contents of the A5 register
  12465. before using the variables, and you must restore the A5 register before your
  12466. routine terminates. Listings 32-4 and 32-6 illustrate the use of the CCB to
  12467. store the pointer to your application’s global variables. 
  12468.  
  12469. If you want to execute a routine each time an unsolicited connection event
  12470. occurs but the interrupt environment is too restrictive, you can specify a NIL
  12471. pointer to the user routine and periodically poll the userFlags field of the
  12472. CCB. 
  12473.  
  12474.     † Warning:  When an unsolicited connection event occurs, you must clear the
  12475.         bit in the userFlags field to 0 or the connection will hang. To ensure
  12476.         that you
  12477.        do not lose any attention messages, you must read any attention messages
  12478.        into
  12479.        an internal buffer before you clear the bit in the userFlags field.  Ê 
  12480.  
  12481. Listing 32-6 is the user routine called by Listing 32-4. When this routine is
  12482. called, it first checks the CCB to determine the source of the interrupt and
  12483. then clears the bit in the userFlags field of the CCB. If the routine has
  12484. received an attention message, the user routine reads the message into an
  12485. internal buffer before it clears the flag bit. The definitions of procedures
  12486. PushA5, GetMyTRCCBA5, and PopA5 are shown in Listing 32-6 for your convenience.
  12487. In a complete application these procedures would be defined in the calling
  12488. routine (Listing 32-4).
  12489.  
  12490. ¿ Listing 32-6   An ADSP user routine 
  12491.  
  12492. PROCEDURE PushA5;             {moves current value of A5 onto stack}
  12493.    INLINE $2F0D;              {MOVE.L A5,-(SP)}
  12494.   
  12495. PROCEDURE GetMyTRCCBA5;       {Retrieves A5 from the head of the TRCCB }
  12496.                               { (pointed to by A1) and sticks it in A5.}
  12497.    INLINE $2A69, $FFFC; {MOVE.L -4(A1), A5}
  12498.  
  12499. PROCEDURE PopA5;              {restores A5 from stack}
  12500.    INLINE $2A5F;              {MOVE.L (SP)+, A5}
  12501.  
  12502. PROCEDURE myConnectionEvtUserRoutine;
  12503.  
  12504. BEGIN
  12505. {The connection received an unexpected connection event.  Find out }
  12506. { what kind and process accordingly.}
  12507.   
  12508.    PushA5;                    {save the current A5}
  12509.    GetMyTRCCBA5;              {set up A5 to point to your application's }
  12510.                               { global variables}
  12511.   
  12512.    WITH dspCCB.u DO
  12513.    BEGIN
  12514.       IF BAND(userFlags, eClosed) <> 0 THEN TellUserItsClosed;
  12515.       IF BAND(userFlags, eTearDown) <> 0 THEN TellUserItsBroken;
  12516.       IF BAND(userFlags, eFwdReset) <> 0 THEN TellUserItsReset;
  12517.       IF BAND(userFlags, eAttention) <> 0 THEN
  12518.       BEGIN      {the event is an attention message}
  12519.          myAttnCode := AttnCode;          {Get the attention code.}
  12520.          CopyAttnMsg(AttnPtr, AttnSize, @myAttnData);
  12521.                               {copy the attention }
  12522.                               { message into our buffer}
  12523.          tempFlag := userFlags;
  12524.          tempCFlag := eAttention;
  12525.          BClr(LongInt(tempFlag), tempCFlag);  {clear the flag}
  12526.          userFlags := tempFlag;
  12527.          {do something with the message}
  12528.       END;
  12529.       gReceivedAnEvent := TRUE;
  12530.    END;
  12531.    PopA5;                                  {restore the current A5}
  12532. END;
  12533.  
  12534. _______________________________________________________________________________
  12535.  
  12536. æKY .DSP…Driver…Routines
  12537. æC ».DSP Driver Routines                                                 AppleTalk Manager
  12538. _______________________________________________________________________________
  12539.  
  12540. The .DSP driver implements the AppleTalk Data Stream Protocol (ADSP). You send
  12541. commands to ADSP and obtain information about ADSP by executing the .DSP driver
  12542. routines described in this section. Each routine is implemented as a call to the
  12543. Device Manager’s PBControl function, as follows:
  12544.  
  12545. FUNCTION PBControl (paramBlock: ParmBlkPtr; async: BOOLEAN) : OSErr;
  12546.  
  12547. The paramBlock parameter is a pointer to the parameter block used by the
  12548. PBControl function for .DSP routines, and the async parameter is a Boolean that
  12549. specifies whether the function is to execute synchronously or asynchronously.
  12550. Set the async parameter to TRUE to execute the function asynchronously.
  12551.  
  12552. The parameter block is shown in “The .DSP Parameter Block” earlier in this
  12553. chapter. The parameters used with each function are described in this section. 
  12554.  
  12555. For a general discussion of the use of ADSP, see “Using ADSP” earlier in this
  12556. chapter.
  12557.  
  12558. _______________________________________________________________________________
  12559.  
  12560. æKY Establishing…&…Terminating…an…ADSP…Connection
  12561. æC »Establishing & Terminating an ADSP Connection                        AppleTalk Manager
  12562. _______________________________________________________________________________
  12563.  
  12564. You can use the routines described in this section to 
  12565.  
  12566.   •  establish a connection end
  12567.  
  12568.   •  set the values for parameters that control the behavior of a connection end
  12569.  
  12570.   •  open a connection
  12571.  
  12572.   •  assign an identification number to a connection end
  12573.  
  12574.   •  close a connection end
  12575.  
  12576.   •  eliminate a connection end
  12577.  
  12578. dspInit
  12579.  
  12580.    Parameter block
  12581.          ¨      16      ioResult              word        result code 
  12582.          Æ      24      ioCRefNum       word        driver reference number
  12583.          Æ      26      csCode                 word         always dspInit
  12584.          ¨      32      ccbRefNum        word        reference number of CCB
  12585.          Æ      34      ccbPtr                    long         pointer to CCB
  12586.          Æ      38      userRoutine       long         pointer to routine to
  12587.          call on 
  12588.  
  12589.  
  12590.  
  12591.          Æ      42      sendQSize           word        size in bytes of the
  12592.          send queue
  12593.          Æ      44      sendQueue          long        pointer to send queue
  12594.          Æ      48      recvQSize            word       size in bytes of the
  12595.          receive queue
  12596.          Æ      50      recvQueue           long       pointer to receive queue
  12597.          Æ      54      attnPtr                   long       pointer to buffer
  12598.          for incoming 
  12599.  
  12600.  
  12601.  
  12602.          ´      58      localSocket  byte  DDP      socket number for this 
  12603.  
  12604.                                                                           end
  12605.  
  12606. The dspInit routine establishes a connection end; that is, it assigns a specific
  12607. socket for use by ADSP and initializes the variables that ADSP uses to maintain
  12608. the connection. The dspInit routine does not open the connection end or
  12609. establish a connection with a remote connection end; you must follow the dspInit
  12610. routine with the dspOpen routine to perform those tasks. Use the dspCLInit
  12611. routine to establish a connection listener. Use the dspRemove routine to
  12612. eliminate a connection end.
  12613.  
  12614. When you send bytes to a remote connection end, ADSP stores the bytes in a
  12615. buffer called the send queue . Until the remote connection end acknowledges
  12616. their receipt, ADSP keeps the bytes you sent in the send queue so that they are
  12617. available to be retransmitted if necessary. When the local connection end
  12618. receives bytes, it stores them in a buffer called the receive queue  until you
  12619. read them. 
  12620.  
  12621. You must allocate memory for the send and receive queues and for a buffer that
  12622. holds incoming attention messages. You must also allocate a nonrelocatable block
  12623. of memory for the CCB for this connection end. 
  12624.  
  12625.    Note:  When you call the dspInit routine, the memory that you allocate
  12626.    becomes
  12627.    the property of ADSP. You cannot write any data to this memory except by
  12628.    calling ADSP routines, and you must ensure that the memory remains
  12629.    locked until you call the dspRemove routine to eliminate the connection
  12630.    end. 
  12631.  
  12632. Fields
  12633.  
  12634. ioResult                         The result of the routine. When you execute the
  12635. routine
  12636.                                          asynchronously, the routine sets this
  12637.                                          parameter to 1 and
  12638.                                          returns a routine result of noErr as
  12639.                                          soon as the routine
  12640.                                          begins execution. When the routine
  12641.                                          completes execution, it
  12642.                                          sets the ioResult parameter to the
  12643.                                          actual result code. 
  12644.  
  12645. ioCRefNum                  The driver reference number. This parameter is
  12646. returned by
  12647.                                           the OpenDriver function. You must
  12648.                                           specify this number
  12649.                                           every time you call the .DSP driver. 
  12650.  
  12651. csCode                            The routine selector, always equal to dspInit
  12652. for this routine.
  12653.  
  12654. ccbRefNum                   The CCB reference number. The dspInit routine
  12655. returns this
  12656.                                           number. You must provide this number
  12657.                                           in all subsequent
  12658.                                           calls to this connection end.
  12659.  
  12660. ccbPtr                               A pointer to the CCB that you allocated.
  12661. The CCB is 242 bytes
  12662.                                           in size and is described in “The ADSP
  12663.                                           Connection Control
  12664.                                           Block” earlier in this chapter.
  12665.  
  12666. userRoutine                   A pointer to a routine that is to be called each
  12667. time the
  12668.                                           connection end receives an unsolicited
  12669.                                           connection event.
  12670.                                           Specify NIL for this parameter if you
  12671.                                           do not want to supply a
  12672.                                           user routine. Connection events and
  12673.                                           user routines are
  12674.                                           discussed in “Writing a User Routine
  12675.                                           for Connection
  12676.                                           Events” earlier in this chapter.
  12677.  
  12678. sendQSize                     The size in bytes of the send queue. A queue size
  12679. of 600 bytes
  12680.                                          should work well for most applications.
  12681.                                          If you are using
  12682.                                          ADSP to send a continuous flow of data,
  12683.                                          a larger data buffer
  12684.                                          improves performance. If your
  12685.                                          application is sending the
  12686.                                          user’s keystrokes, a smaller buffer
  12687.                                          should be adequate. The
  12688.                                          constant minDSPQueueSize indicates the
  12689.                                          minimum queue
  12690.                                          size that you can use.
  12691.  
  12692. sendQueue                   A pointer to the send queue that you allocated. 
  12693.  
  12694. recvQSize                     The size in bytes of the receive queue. A queue
  12695. size of 600
  12696.                                         bytes should work well for most
  12697.                                         applications. If you are using
  12698.                                         ADSP to receive a continuous flow of
  12699.                                         data, a larger data
  12700.                                         buffer improves performance. If your
  12701.                                         application is receiving
  12702.                                         a user’s keystrokes, a smaller buffer
  12703.                                         should be adequate. The
  12704.                                         constant minDSPQueueSize indicates the
  12705.                                         minimum queue
  12706.                                         size that you can use.
  12707.  
  12708. recvQueue                   A pointer to the receive queue that you allocated.
  12709.  
  12710. attnPtr                           A pointer to the attention-message buffer that
  12711. you allocated.
  12712.                                         The attention-message buffer must be the
  12713.                                         size of the constant
  12714.                                          attnBufSize.
  12715.  
  12716. localSocket                   The DDP socket number of the socket that you want
  12717. ADSP to
  12718.                                         use for this connection end. Specify 0
  12719.                                         for this parameter to
  12720.                                         cause ADSP to assign the socket. In the
  12721.                                         latter case, ADSP
  12722.                                         returns the socket number when the
  12723.                                         dspInit routine
  12724.                                         completes execution.
  12725.  
  12726.    Result codes
  12727.           noErr                                 0        No error
  12728.           ddpSktErr                      –91       Error opening socket
  12729.           errDSPQueueSize    –1274       Send or receive queue is too small
  12730.  
  12731.  dspOptions 
  12732.  
  12733.    Parameter block
  12734.         ¨       16      ioResult               word            result code 
  12735.         Æ       24      ioCRefNum        word            driver reference
  12736.         number
  12737.         Æ       26      csCode                  word            always
  12738.         dspOptions
  12739.         Æ       32      ccbRefNum         word           reference number of CCB
  12740.         Æ       34      sendBlocking      word           send-blocking threshold
  12741.         Æ       38      badSeqMax           byte             threshold to send
  12742.         retransmit advice
  12743.         Æ       39      useCheckSum     byte             use DDP checksum?
  12744.  
  12745. The dspOptions routine allows you to set values for several parameters that
  12746. affect the behavior of the local connection end. You can set the options for any
  12747. established connection end, whether open or not.
  12748.  
  12749. Fields
  12750.  
  12751. ioResult                           The result of the routine. When you execute
  12752. the routine
  12753.                                            asynchronously, the routine sets this
  12754.                                            parameter to 1 and
  12755.                                            returns a routine result of noErr as
  12756.                                            soon as the routine
  12757.                                            begins execution. When the routine
  12758.                                            completes execution, it
  12759.                                            sets the ioResult parameter to the
  12760.                                            actual result code. 
  12761.  
  12762. ioCRefNum                   The driver reference number. This parameter is
  12763. returned by
  12764.                                           the OpenDriver function. You must
  12765.                                           specify this number
  12766.                                           every time you call the .DSP driver. 
  12767.  
  12768. csCode                             The routine selector, always equal to
  12769. dspOptions for this
  12770.                                           routine.
  12771.  
  12772. ccbRefNum                    The CCB reference number that was returned by the
  12773. dspInit
  12774.                                           routine.
  12775.  
  12776. sendBlocking                 The maximum number of bytes that may accumulate in
  12777. the
  12778.                                           send queue before ADSP sends a packet
  12779.                                           to the remote
  12780.                                           connection end. ADSP sends a packet
  12781.                                           before the maximum
  12782.                                           number of bytes accumulates if the
  12783.                                           period specified by the
  12784.                                           send timer expires, if you execute the
  12785.                                           dspWrite routine with
  12786.                                           the flush parameter set to 1, or if a
  12787.                                           connection event
  12788.                                           requires that the local connection end
  12789.                                           send an
  12790.                                           acknowledgment packet to the remote
  12791.                                           connection end.
  12792.  
  12793.                                          You can set the sendBlocking parameter
  12794.                                          to any value from 1
  12795.                                          byte to the maximum size of a packet
  12796.                                          (572 bytes). If you set
  12797.                                          the sendBlocking parameter to 0, the
  12798.                                          current value for this
  12799.                                          parameter is not changed. The default
  12800.                                          value for the
  12801.                                          sendBlocking parameter is 16 bytes.
  12802.  
  12803. badSeqMax                   The maximum number of out-of-sequence data packets
  12804. that
  12805.                                         the local connection end can receive
  12806.                                         before requesting the
  12807.                                         remote connection end to retransmit the
  12808.                                         missing data.
  12809.                                         Because a connection end does not
  12810.                                         acknowledge the receipt of
  12811.                                         a data packet received out of sequence,
  12812.                                         the  retransmit timer
  12813.                                         of the remote connection end will expire
  12814.                                         eventually and the
  12815.                                         connection end will retransmit the data.
  12816.                                         The badSeqMax
  12817.                                         parameter allows you to cause the data
  12818.                                         to be retransmitted
  12819.                                         before the retransmit timer of the
  12820.                                         remote connection end has
  12821.                                         expired.
  12822.  
  12823.                                         You can set the badSeqMax parameter to
  12824.                                         any value from 1 to
  12825.                                         255. If you set the badSeqMax parameter
  12826.                                         to 0, the current
  12827.                                         value for this parameter is not changed.
  12828.                                         The default value for
  12829.                                         the badSeqMax parameter is 3.
  12830.  
  12831. useCheckSum             A flag specifying whether DDP should compute a checksum
  12832.                                         and include it in each packet that it
  12833.                                         sends to the remote
  12834.                                         connection end. Set this parameter to 1
  12835.                                         if you want DDP to
  12836.                                         use checksums or to 0 if you do not want
  12837.                                         DDP to use
  12838.                                         checksums. The default value for
  12839.                                         useCheckSum is 0.
  12840.  
  12841.                                         ADSP cannot include a checksum in a
  12842.                                         packet that has a short
  12843.                                         DDP header; that is, a packet being sent
  12844.                                         over LocalTalk to a
  12845.                                         remote socket that is on the same cable
  12846.                                         as the local socket.
  12847.                                         Note that the useCheckSum parameter
  12848.                                         affects only whether
  12849.                                         ADSP includes a checksum in a packet
  12850.                                         that it is sending. If
  12851.                                         ADSP receives a packet that includes a
  12852.                                         checksum, it validates
  12853.                                         the checksum regardless of the setting
  12854.                                         of the useCheckSum
  12855.                                         parameter. 
  12856.  
  12857. Result codes
  12858.         noErr                            0        No error
  12859.         errRefNum        –1280        Bad connection reference number
  12860. _______________________________________________________________________________
  12861.  
  12862. æKY Establishing…&…Terminating…an…ADSP…Connection…(cont'd)
  12863. æC »Establishing & Terminating an ADSP Connection (cont'd)               AppleTalk Manager
  12864. _______________________________________________________________________________
  12865.  
  12866. dspOpen
  12867.  
  12868. Parameter block
  12869.        ¨        16        ioResult                 word        result code 
  12870.        Æ        24        ioCRefNum          word        driver reference number
  12871.        Æ        26        csCode                    word        always dspOpen
  12872.        Æ        32        ccbRefNum           word        reference number of
  12873.        CCB
  12874.        ¨        34        localCID                 word        ID of this
  12875.        connection end
  12876.        ´        36        remoteCID             word       ID of remote
  12877.        connection end
  12878.        ´        38        remoteAddress     long         remote internet address
  12879.        Æ        42        filterAddress         long         filter for open
  12880.        connection requests
  12881.        ´        46        sendSeq                  long         initial send
  12882.        sequence number
  12883.        ´        50        sendWindow        word       initial size of remote
  12884.        receive queue
  12885.        Æ        52        recvSeq                   long        initial receive
  12886.        sequence number
  12887.        ´        56        attnSendSeq          long         attention send
  12888.        sequence number
  12889.        Æ        60        attnRecvSeq          long         attention receive
  12890.        sequence number
  12891.        Æ        64        ocMode                   byte
  12892.        connection-opening mode
  12893.        Æ        65        ocInterval               byte         interval between
  12894.        open requests
  12895.        Æ        66        ocMaximum          byte         retries of
  12896.        open-connection request
  12897.  
  12898. You use the ocMode field of the parameter block to specify the opening mode that
  12899. the dspOpen routine is to use. The dspOpen routine puts a connection end into
  12900. one of the four following opening modes: 
  12901.  
  12902.   •  The ocRequest mode, in which ADSP attempts to open a connection with the
  12903.        socket at the internet address you specify with the remoteAddress
  12904.        parameter. If
  12905.        the socket you specify as a remote address is a connection listener, it
  12906.        is possible
  12907.        that your application will receive a connection acknowledgment and
  12908.        request
  12909.        from a different address than the one to which you sent the
  12910.        open-connection
  12911.        request. You can use the filterAddress parameter to restrict the
  12912.        addresses with
  12913.        which you will accept a connection. 
  12914.  
  12915.        The dspOpen routine completes execution in the ocRequest mode when one of
  12916.         the following occurs: ADSP establishes a connection, your connection end
  12917.         receives a connection denial from the remote connection end, your
  12918.         connection
  12919.         end denies the connection request returned by a connection listener, or
  12920.         ADSP
  12921.         cannot complete the connection within the maximum number of retries that
  12922.         you specified with the ocMaximum parameter.
  12923.  
  12924.   •  The ocPassive mode, in which the connection end waits to receive an
  12925.        open-connection request from a remote connection end. You can use the
  12926.        filterAddress parameter to restrict the addresses from which you will
  12927.        accept a
  12928.        connection request.
  12929.  
  12930.        The dspOpen routine completes execution in the ocPassive mode when ADSP
  12931.        establishes a connection or when either connection end receives a
  12932.        connection
  12933.        denial.
  12934.  
  12935.   •  The ocAccept mode, used by connection servers to complete an
  12936.       open-connection dialog. When a connection server is informed by its
  12937.       connection listener that the connection listener has received an
  12938.       open-connection request, the connection server calls the dspInit routine
  12939.       to
  12940.       establish a connection end and then calls the dspOpen routine in ocAccept
  12941.       mode to complete the connection. You must obtain the following parameters
  12942.       from the dspCLListen routine and provide them to the dspOpen routine:
  12943.       remoteAddress, remoteCID, sendSeq, sendWindow, and attnSendSeq.
  12944.       Connection listeners and connection servers are described in “Creating and
  12945.       Using a Connection Listener,” earlier in this chapter, and in
  12946.       “Establishing and
  12947.       Terminating an ADSP Connection ,” later in this chapter.
  12948.  
  12949.       The dspOpen routine completes execution in the ocAccept mode when ADSP
  12950.       establishes a connection or when either connection end receives a
  12951.       connection
  12952.       denial.
  12953.  
  12954.   •  The ocEstablish mode, in which ADSP considers the connection end
  12955.   established
  12956.       and the connection state open. This mode is for use by clients that
  12957.       determine
  12958.       their connection-opening parameters without using ADSP or the .DSP driver
  12959.       to
  12960.       do so. 
  12961.  
  12962.       You must first use the dspInit routine to establish a connection end and
  12963.       then
  12964.       execute the dspNewCID routine to obtain an identification number (ID) for
  12965.       the
  12966.       local connection end. You must then communicate with the remote connection
  12967.       end to send it the local connection ID and to determine the values of the
  12968.       following parameters: remoteAddress, remoteCID, sendSeq, sendWindow,
  12969.       recvSeq, attnSendSeq, and attnRecvSeq. Only then can you execute the
  12970.       dspOpen
  12971.       routine in the ocEstablish mode.
  12972.  
  12973.       The dspOpen routine completes execution in the ocEstablish mode
  12974.       immediately. 
  12975.  
  12976.        The use of parameters by the dspOpen routine depends on the mode in which
  12977.         the routine is executed, as follows:
  12978.  
  12979. ocRequest                  ocPassive                   ocAccept                
  12980. ocEstablish
  12981.  
  12982. ¨ ioResult                 ¨   ioResult               ¨   ioResult             
  12983. ¨   ioResult
  12984. Æ  ioCRefNum         Æ   ioCRefNum       Æ   ioCRefNum        Æ   ioCRefNum  
  12985. Æ  csCode                   Æ   csCode                  Æ   csCode             
  12986. Æ   csCode
  12987. Æ  ccbRefNum          Æ   ccbRefNum        Æ    ccbRefNum        Æ   ccbRefNum
  12988. ¨  localCID                ¨   localCID               ¨   localCID             
  12989. —  localCID
  12990. ¨  remoteCID           ¨   remoteCID           Æ   remoteCID           Æ
  12991. remoteCID
  12992. Æ  remoteAddress   ¨   remoteAddress   Æ   remoteAddress   Æ  remoteAddress
  12993. Æ  filterAddress        Æ   filterAddress       —  filterAddress       —
  12994. filterAddress
  12995. ¨  sendSeq                 ¨   sendSeq                Æ   sendSeq              
  12996. Æ   sendSeq
  12997. ¨  sendWindow       ¨   sendWindow     Æ   sendWindow       Æ   sendWindow
  12998. — recvSeq                 —  recvSeq                 —  recvSeq                
  12999. Æ   recvSeq
  13000. ¨  attnSendSeq         ¨   attnSendSeq        Æ   attnSendSeq         Æ
  13001. attnSendSeq
  13002. — attnRecvSeq        —  attnRecvSeq         —  attnRecvSeq        Æ
  13003. attnRecvSeq
  13004. Æ  ocMode                 Æ   ocMode                  Æ   ocMode               
  13005. Æ   ocMode
  13006. Æ  ocInterval             Æ   ocInterval             Æ   ocInterval            —
  13007. ocInterval
  13008. Æ  ocMaximum        Æ   ocMaximum        Æ   ocMaximum       —  ocMaximum
  13009.  
  13010. Key:  Æ input    ¨ output    — not used
  13011.  
  13012. Fields
  13013.  
  13014. ioResult                     The result of the routine. When you execute the
  13015. routine
  13016.                                      asynchronously, the routine sets this
  13017.                                      parameter to 1 and
  13018.                                      returns a routine result of noErr as soon
  13019.                                      as the routine begins
  13020.                                      execution. When the routine completes
  13021.                                      execution, it sets the
  13022.                                      ioResult parameter to the actual result
  13023.                                      code. 
  13024.  
  13025. ioCRefNum             The driver reference number. This parameter is returned by
  13026. the
  13027.                                     OpenDriver function. You must specify this
  13028.                                     number every time
  13029.                                      you call the .DSP driver. 
  13030.  
  13031. csCode                       The routine selector, always equal to dspOpen for
  13032. this routine. 
  13033.  
  13034. ccbRefNum              The CCB reference number that was returned by the dspInit
  13035.                                     routine for the connection end that you want
  13036.                                     to use.
  13037.  
  13038. localCID                     The identification number of the local connection
  13039. end. This
  13040.                                      number is assigned by ADSP when the
  13041.                                      connection is opened.
  13042.                                      ADSP includes this number in every packet
  13043.                                      sent to a remote
  13044.                                      connection end. Before you call the dspOpen
  13045.                                      routine in
  13046.                                      ocEstablish mode, you must call the
  13047.                                      dspNewCID routine to
  13048.                                      cause ADSP to assign this value.
  13049.  
  13050. remoteCID               The identification number of the remote connection end.
  13051. This
  13052.                                     parameter is returned by the dspOpen routine
  13053.                                     in the ocRequest
  13054.                                     and ocPassive modes. A connection server
  13055.                                     must provide this
  13056.                                     number to the dspOpen routine when the
  13057.                                     server executes the
  13058.                                     routine in ocAccept mode; in this case, the
  13059.                                     connection server
  13060.                                     obtains the remoteCID value from the
  13061.                                     dspCLListen routine.
  13062.                                     You must provide the remoteCID value to the
  13063.                                     dspOpen routine
  13064.                                     when you use the routine in ocEstablish
  13065.                                     mode. 
  13066.  
  13067. remoteAddress       The internet address of the remote socket with which you
  13068. wish
  13069.                                    to establish communications. This address
  13070.                                    consists of a 2-byte
  13071.                                    network number, a 1-byte node ID, and a
  13072.                                    1-byte socket number.
  13073.                                    You must provide this parameter when you call
  13074.                                    the dspOpen
  13075.                                    routine in the ocRequest or ocEstablish
  13076.                                    modes. This parameter
  13077.                                    is returned by the dspOpen routine when you
  13078.                                    call the routine in
  13079.                                    the ocPassive mode. When you call the dspOpen
  13080.                                    routine in the
  13081.                                    ocAccept mode, you must use the value for the
  13082.                                    remoteAddress
  13083.                                    parameter that was returned by the
  13084.                                    dspCLListen routine. 
  13085.  
  13086. filterAddress           The internet address of the socket from which you will
  13087. accept a
  13088.                                    connection request. The address consists of
  13089.                                    three fields: a 2-byte
  13090.                                    network number, a 1-byte node ID, and a
  13091.                                    1-byte socket number.
  13092.                                    Specify 0 for any of these fields for which
  13093.                                    you wish to impose no
  13094.                                    restrictions. If you specify a filter address
  13095.                                    of $00082500, for
  13096.                                    example, the connection end accepts a
  13097.                                    connection request from
  13098.                                    any socket at node $25 of network $0008. Set
  13099.                                    the filterAddress
  13100.                                    parameter equal to the remoteAddress
  13101.                                    parameter to accept a
  13102.                                    connection only with the socket to which you
  13103.                                    sent a connection
  13104.                                    request.
  13105.  
  13106.                                    When you execute the dspOpen routine in the
  13107.                                    ocPassive mode,
  13108.                                    you can receive a connection request from any
  13109.                                    ADSP
  13110.                                    connection end on the internet. When you
  13111.                                    execute the dspOpen
  13112.                                    routine in the ocRequest mode, your
  13113.                                    connection end can
  13114.                                    receive a connection request acknowledgment
  13115.                                    from an address
  13116.                                    different from the one you specified in the
  13117.                                    remoteAddress
  13118.                                    parameter only if the remote address you
  13119.                                    specified was that of a
  13120.                                    connection listener. In either case, you can
  13121.                                    use the filterAddress
  13122.                                    parameter to avoid acknowledging unwanted
  13123.                                    connection
  13124.                                    requests. 
  13125.  
  13126.                                   When you execute the dspOpen routine in the
  13127.                                   ocAccept mode,
  13128.                                    your connection listener has already received
  13129.                                    and decided to
  13130.                                    accept the connection request. You can
  13131.                                    specify a filter address for
  13132.                                    a connection listener with the dspCLListen
  13133.                                    routine. A
  13134.                                    connection server can use the dspCLDeny
  13135.                                    routine to deny a
  13136.                                    connection request that was accepted by its
  13137.                                    connection listener.
  13138.  
  13139.                                    You cannot use the filter address when you
  13140.                                    execute the dspOpen
  13141.                                    routine in ocEstablish mode.
  13142.  
  13143. sendSeq                    The sequence number of the first byte that the local
  13144. connection
  13145.                                    end will send to the remote connection end.
  13146.                                    ADSP uses this
  13147.                                    number to coordinate communications and to
  13148.                                    check for errors.
  13149.                                    ADSP returns a value for the sendSeq
  13150.                                    parameter when you
  13151.                                    execute the dspOpen routine in the ocRequest
  13152.                                    or ocPassive
  13153.                                    modes. When you execute the dspOpen routine
  13154.                                    in the ocAccept
  13155.                                    mode, you must specify the value for the
  13156.                                    sendSeq parameter
  13157.                                    that was returned by the dspCLListen routine.
  13158.                                    You must
  13159.                                    provide the value for this parameter when you
  13160.                                    execute the
  13161.                                    dspOpen routine in the ocEstablish mode.
  13162.  
  13163. sendWindow         The sequence number of the last byte that the remote
  13164. connection
  13165.                                   end has buffer space to receive. ADSP uses
  13166.                                   this number to
  13167.                                   coordinate communications and to check for
  13168.                                   errors. ADSP
  13169.                                   returns a value for the sendWindow parameter
  13170.                                   when you
  13171.                                   execute the dspOpen routine in the ocRequest
  13172.                                   or ocPassive
  13173.                                   modes. When you execute the dspOpen routine in
  13174.                                   the ocAccept
  13175.                                   mode, you must specify the value for the
  13176.                                   sendWindow
  13177.                                   parameter that was returned by the dspCLListen
  13178.                                   routine. You
  13179.                                   must provide the value for this parameter when
  13180.                                   you execute the
  13181.                                   dspOpen routine in the ocEstablish mode.
  13182.  
  13183. recvSeq                   The sequence number of the next byte that the local
  13184. connection
  13185.                                  end expects to receive. ADSP uses this number
  13186.                                  to coordinate
  13187.                                  communications and to check for errors. You
  13188.                                  must provide the
  13189.                                  value for this parameter when you execute the
  13190.                                  dspOpen routine
  13191.                                  in the ocEstablish mode. The dspOpen routine
  13192.                                  does not use this
  13193.                                  parameter when you execute it in any other
  13194.                                  mode.
  13195.  
  13196. attnSendSeq          The sequence number of the next attention packet that the
  13197. local
  13198.                                  connection end will transmit. ADSP uses this
  13199.                                  number to
  13200.                                  coordinate communications and to check for
  13201.                                  errors. ADSP
  13202.                                  returns a value for the attnSendSeq parameter
  13203.                                  when you execute
  13204.                                  the dspOpen routine in the ocRequest or
  13205.                                  ocPassive modes. When
  13206.                                  you execute the dspOpen routine in the ocAccept
  13207.                                  mode, you
  13208.                                  must specify the value for the attnSendSeq
  13209.                                  parameter that was
  13210.                                  returned by the dspCLListen routine. You must
  13211.                                  provide the
  13212.                                  value for this parameter when you execute the
  13213.                                  dspOpen routine
  13214.                                  in the ocEstablish mode.
  13215.  
  13216. attnRecvSeq          The sequence number of the next attention packet that the
  13217. local
  13218.                                  connection end expects to receive. ADSP uses
  13219.                                  this number to
  13220.                                  coordinate communications and to check for
  13221.                                  errors. You must
  13222.                                  provide the value for this parameter when you
  13223.                                  execute the
  13224.                                  dspOpen routine in the ocEstablish mode. The
  13225.                                  dspOpen routine
  13226.                                  does not use this parameter when you execute it
  13227.                                  in any other
  13228.                                  mode.
  13229.  
  13230. ocMode                   The mode in which the dspOpen routine is to operate, as
  13231.                                   follows: 
  13232.  
  13233.                                   Mode               Value            Meaning
  13234.                                   ocRequest        1                     ADSP
  13235.                                   attempts to open a connection
  13236.                                                                                
  13237.                                                                                
  13238.                                                                                
  13239.                                                                                
  13240.                                                                                
  13241.  
  13242.   
  13243.                                   ocPassive         2                      The
  13244.                                   connection end waits to receive
  13245.                                                                                
  13246.                                                                                
  13247.                                                                                
  13248.  
  13249.  
  13250.                                   ocAccept          3                       The
  13251.                                   connection server accepts and
  13252.                                                                                
  13253.                                                                                
  13254.                                                                                
  13255.                                                                                
  13256.  
  13257.                                                                                
  13258.                                                                                
  13259.  
  13260.  
  13261.                                    ocEstablish     4                       ADSP
  13262.                                    considers the connection
  13263.                                                                                
  13264.                                                                                
  13265.                                                                                
  13266.                                                                                
  13267.                                                                                
  13268.  
  13269.                                                                                
  13270.                                                                                
  13271.                                                                                
  13272.                                                                                
  13273.                                                                                
  13274.  
  13275.                                                                                
  13276.                                                                                
  13277.                                                                                
  13278.                                                                                
  13279.  
  13280.  
  13281. ocInterval               The period between transmissions of open-connection
  13282. requests.
  13283.                                   If the remote connection end does not
  13284.                                   acknowledge or deny an
  13285.                                   open-connection request, ADSP retransmits the
  13286.                                   request after a
  13287.                                   time period specified by this parameter. The
  13288.                                   time period used by
  13289.                                   ADSP is (ocInterval ¥ 10) ticks; or
  13290.                                   (ocInterval / 6) seconds. For
  13291.                                   example, if you set the ocInterval parameter
  13292.                                   to 3, the time period
  13293.                                   between retransmissions is 30 ticks (1/2
  13294.                                   second). You can set the
  13295.                                   ocInterval parameter to any value from 1 (1/6
  13296.                                   second) to 180 (30
  13297.                                   seconds). If you specify 0 for the ocInterval
  13298.                                   parameter, ADSP uses
  13299.                                   the default value of 6 (1 second).
  13300.  
  13301.                                   You must provide a value for the ocInterval
  13302.                                   parameter when
  13303.                                   you execute the dspOpen routine in the
  13304.                                   ocRequest, ocPassive, or
  13305.                                   ocAccept modes. The dspOpen routine does not
  13306.                                   use this
  13307.                                   parameter when you execute it in the
  13308.                                   ocEstablish mode.
  13309.  
  13310. ocMaximum          The maximum number of times to retransmit an
  13311.                                   open-connection request before ADSP terminates
  13312.                                   execution of
  13313.                                   the dspOpen routine. If you specify 0 for the
  13314.                                   ocMaximum
  13315.                                   parameter, ADSP uses the default value of 3.
  13316.                                   If you specify 255
  13317.                                   for the ocMaximum parameter, ADSP retransmits
  13318.                                   the
  13319.                                   open-connection request indefinitely until the
  13320.                                   remote
  13321.                                   connection end either acknowledges or denies
  13322.                                   the request.
  13323.  
  13324.                                   You must provide a value for the ocMaximum
  13325.                                   parameter when 
  13326.                                   you execute the dspOpen routine in the
  13327.                                   ocRequest, ocPassive, or
  13328.                                   ocAccept modes. The dspOpen routine does not
  13329.                                   use this
  13330.                                   parameter when you execute it in the
  13331.                                   ocEstablish mode.
  13332.  
  13333.    Result codes
  13334.          noErr                                0             No error
  13335.          errOpenDenied      –1273             Open request denied by recepient
  13336.          errOpening             –1277              Attempt to open connection
  13337.          failed
  13338.          errState                    –1278              Connection end must be
  13339.          closed
  13340.          errAborted              –1279              Request aborted by dspRemove
  13341.          or dspClose
  13342.                                                                     routine
  13343.          errRefNum            –1280              Bad connection reference number
  13344.  
  13345. dspNewCID 
  13346.  
  13347.    Parameter block
  13348.             ¨  16            ioResult                 word           result code
  13349.  
  13350.             Æ  24           ioCRefNum           word           driver reference
  13351.             number
  13352.             Æ  26           csCode                     word           always
  13353.             dspNewCID
  13354.             Æ  32           ccbRefNum            word          reference number
  13355.             of CCB
  13356.             ¨  34           newCID                   word          ID of new
  13357.             connection
  13358.  
  13359. The dspNewCID routine causes ADSP to assign an ID to a connection end without
  13360. opening the connection end or attempting to establish a connection with a remote
  13361. connection end. Use this routine only if you implement your own protocol to
  13362. establish communications with a remote connection end. You must first use the
  13363. dspInit routine to establish a connection end. Next, you must call the dspNewCID
  13364. routine to obtain a connection-end ID. Then you must establish communication
  13365. with a remote connection end and pass the ID to the remote connection end.
  13366. Finally, you must call the dspOpen routine in ocEstablish mode to cause ADSP to
  13367. open the connection. See the description of the dspOpen routine for more
  13368. information on establishing a connection in this fashion.
  13369.  
  13370. The ioResult parameter returns the result of the routine. If you call the
  13371. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13372. execution, and it changes the field to the actual result code when it completes
  13373. execution. The ioCRefNum parameter is the driver reference number returned by
  13374. the OpenDriver function. You must specify this number every time you call the
  13375. .DSP driver. The csCode parameter is the routine selector; it is always
  13376. dspNewCID for this routine. The ccbRefNum parameter is the CCB reference number
  13377. that was returned by the dspInit routine. The newCID parameter is the
  13378. connection-end ID returned by this routine. You must provide this number to the
  13379. client of the remote connection end so that it can use it for the remoteCID
  13380. parameter when it calls the dspOpen routine.
  13381.  
  13382.    Result codes
  13383.           noErr                        0        No error
  13384.           errState            –1278        Connection is not closed
  13385.          errRefNum     –1280        Bad connection reference number
  13386.  
  13387. dspClose 
  13388.  
  13389.    Parameter block
  13390.          ¨            16            ioResult              word          result
  13391.          code 
  13392.          Æ            24            ioCRefNum       word         driver
  13393.          reference number
  13394.          Æ            26            csCode                  word         always
  13395.          dspClose
  13396.          Æ           32            ccbRefNum         word         reference
  13397.          number of CCB
  13398.          Æ           34            abort                      byte
  13399.          abort send requests if not 0
  13400.  
  13401. The dspClose routine closes the connection end. The connection end is still
  13402. established; that is, ADSP retains ownership of the CCB, send queue, receive
  13403. queue, and attention-message buffer. You can continue to read bytes from the
  13404. receive queue after you have called the dspClose routine. Use the dspRemove
  13405. routine instead of the dspClose routine if you are through reading bytes from
  13406. the receive queue and want to release the memory associated with the connection
  13407. end. The dspClose routine does not return an error if you call it for a
  13408. connection end that is already closed.
  13409.  
  13410. The ioResult parameter returns the result of the routine. If you call the
  13411. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13412. execution, and it changes the field to the actual result code when it completes
  13413. execution. The ioCRefNum parameter is the driver reference number returned by
  13414. the OpenDriver function. You must specify this number every time you call the
  13415. .DSP driver. The csCode parameter is the routine selector; it is always dspClose
  13416. for this routine. The ccbRefNum parameter is the CCB reference number that was
  13417. returned by the dspInit routine. If the abort parameter is nonzero, ADSP cancels
  13418. any outstanding requests to send data packets (such as the dspAttention routine)
  13419. and discards all data in the send queue. If the abort parameter is 0, ADSP does
  13420. not close the connection end until all of the data in the send queue and all
  13421. outstanding attention messages have been sent and acknowledged.
  13422.  
  13423.    Result codes
  13424.          noErr                          0         No error
  13425.          errRefNum      –1280         Bad connection reference number
  13426.  
  13427. dspRemove 
  13428.  
  13429.    Parameter block
  13430.          ¨          16            ioResult             word        result code 
  13431.          Æ          24            ioCRefNum      word       driver reference
  13432.          number
  13433.          Æ          26            csCode                word       always
  13434.          dspRemove
  13435.          Æ          32            ccbRefNum       word      reference number of
  13436.          CCB
  13437.          Æ          34            abort                    byte        abort
  13438.          connection if not 0
  13439.  
  13440. The dspRemove routine closes any open connection and eliminates the connection
  13441. end; that is, ADSP no longer retains control of the CCB, send queue, receive
  13442. queue, and attention-message buffer. You cannot continue to read bytes from the
  13443. receive queue after you have called the dspRemove routine. After you call the
  13444. dspRemove routine, you can release all of the memory you allocated for the
  13445. connection end if you do not intend to reopen the connection end.
  13446.  
  13447. The ioResult parameter returns the result of the routine. If you call the
  13448. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13449. execution, and it changes the field to the actual result code when it completes
  13450. execution. The ioCRefNum parameter is the driver reference number returned by
  13451. the OpenDriver function. You must specify this number every time you call the
  13452. .DSP driver. The csCode parameter is the routine selector, always dspRemove for
  13453. this routine. The ccbRefNum parameter is the CCB reference number that was
  13454. returned by the dspInit routine. If the abort parameter is nonzero, ADSP cancels
  13455. any outstanding requests to send data packets (such as the dspAttention routine)
  13456. and discards all data in the send queue. If the abort parameter is 0, ADSP does
  13457. not close the connection end until all of the data in the send queue has been
  13458. sent and acknowledged.
  13459.  
  13460.    Result codes
  13461.           noErr                         0         No error
  13462.           errRefNum     –1280         Bad connection reference number
  13463. _______________________________________________________________________________
  13464.  
  13465. æKY Establishing…&…Terminating…an…ADSP…Connection…Listener
  13466. æC »Establishing & Terminating an ADSP Connection Listener               AppleTalk Manager
  13467. _______________________________________________________________________________
  13468.  
  13469. A connection listener is a special kind of connection end that listens for
  13470. open-connection requests from remote connection ends. Connection listeners are
  13471. used by connection servers; that is, programs that assign a socket for the local
  13472. connection end only after they receive a connection request from a remote
  13473. connection end. A single connection listener can receive connection requests
  13474. from any number of remote connection ends. 
  13475.  
  13476. You can use the routines in this section to
  13477.  
  13478.   •  establish a connection listener
  13479.  
  13480.   •  cause the connection listener to wait for a connection request
  13481.  
  13482.   •  deny a connection request
  13483.  
  13484.   •  close and eliminate a connection listener
  13485.  
  13486. dspCLInit 
  13487.  
  13488.    Parameter block
  13489.          ¨       16        ioResult                word       result code 
  13490.          Æ       24        ioCRefNum         word       driver reference number
  13491.          Æ       26        csCode                   word       always dspCLInit
  13492.          ¨       32        ccbRefNum          word       reference number of CCB
  13493.          Æ       34        ccbPtr                      long       pointer to CCB
  13494.          ´       58        localSocket            byte        local DDP socket
  13495.          number
  13496.  
  13497. The dspCLInit routine establishes a connection listener; that is, it assigns a
  13498. specific socket for use by ADSP and initializes the variables that ADSP uses to
  13499. maintain a connection listener. The dspCLInit routine does not cause the
  13500. connection listener to listen for connection requests; you must follow the
  13501. dspCLInit routine with the dspCLListen routine to activate the connection
  13502. listener. Use the dspInit routine to establish a connection end that is not a
  13503. connection listener. Use the dspCLRemove routine to eliminate a connection
  13504. listener.
  13505.  
  13506. The ioResult parameter returns the result of the routine. If you call the
  13507. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13508. execution, and it changes the field to the actual result code when it completes
  13509. execution. The ioCRefNum parameter is the driver reference number returned by
  13510. the OpenDriver function. You must specify this number every time you call the
  13511. .DSP driver. The csCode parameter is the routine selector, always dspCLInit for
  13512. this routine. The dspCLInit routine returns the ccbRefNum parameter, which is
  13513. the CCB reference number. You must provide this number in all subsequent
  13514. dspCLListen and dspCLRemove calls to this connection listener. 
  13515.  
  13516. You must allocate memory for a CCB before you call the dspCLInit routine. The
  13517. ccbPtr parameter is a pointer to the CCB that you allocated. The CCB is 242
  13518. bytes and is described in “The ADSP Connection Control Block” earlier in this
  13519. chapter.
  13520.  
  13521. The localSocket parameter is the DDP socket number of the socket that you want
  13522. ADSP to use for this connection end. Specify 0 for this parameter to cause ADSP
  13523. to assign the socket. In the latter case, ADSP returns the socket number when
  13524. the dspCLInit routine completes execution.
  13525.  
  13526.    Result codes
  13527.          noErr                     0       No error
  13528.          ddpSktErr         –91       Error opening socket
  13529.  
  13530. dspCLListen 
  13531.  
  13532.    Parameter block
  13533.         ¨      16       ioResult               word      result code 
  13534.         Æ      24       ioCRefNum       word      driver reference number
  13535.        Æ       26       csCode                  word     always dspCLListen
  13536.        Æ       32       ccbRefNum         word     reference number of CCB
  13537.        ¨       36       remoteCID           word     ID of remote connection end
  13538.        ¨       38       remoteAddress   long      remote internet address
  13539.        Æ       42       filterAddress       long      filter for open-connection
  13540.        requests
  13541.        ¨       46       sendSeq                long      initial send sequence
  13542.        number
  13543.        ¨       50       sendWindow      word     initial size of remote receive
  13544.        queue
  13545.        ¨       56      attnSendSeq          long      attention send sequence
  13546.        number
  13547.  
  13548. The dspCLListen routine causes a connection listener to listen for connection
  13549. requests. You must have already used the dspCLInit routine to establish a
  13550. connection listener before using the dspCLListen routine. The dspCLListen
  13551. routine is used only by connection servers.
  13552.  
  13553. When ADSP receives an open-connection request from a socket that satisfies the
  13554. address requirements of the filterAddress parameter, it returns values for the
  13555. remoteCID, remoteAddress, sendSeq, sendWindow, and attnSendSeq parameters and
  13556. completes execution of the dspCLListen routine. You must then either accept the
  13557. open-connection request by calling the dspOpen routine in the ocAccept mode or
  13558. deny the request by calling the dspCLDeny routine.
  13559.  
  13560. You can call the dspCLListen routine several times, specifying the same
  13561. connection listener. For example, if you wanted to accept connections from any
  13562. or all of three different addresses, you could call the dspCLListen routine
  13563. three times with a different value for the filterAddress parameter each time.
  13564. Note that you must execute the dspCLListen routine asynchronously to take
  13565. advantage of this feature.
  13566.  
  13567. Fields
  13568.  
  13569. ioResult                        The result of the routine. When you execute the
  13570. routine
  13571.                                         asynchronously, the routine sets this
  13572.                                         parameter to 1 and
  13573.                                         returns a routine result of noErr as
  13574.                                         soon as the routine begins
  13575.                                         execution. When the routine completes
  13576.                                         execution, it sets the
  13577.                                         ioResult parameter to the actual result
  13578.                                         code. 
  13579.  
  13580. ioCRefNum                The driver reference number. This parameter is returned
  13581. by
  13582.                                         the OpenDriver function. You must
  13583.                                         specify this number
  13584.                                         every time you call the .DSP driver. 
  13585.  
  13586. csCode                           The routine selector, always dspCLListen for
  13587. this routine.
  13588.  
  13589. ccbRefNum                 The CCB reference number that was returned by the
  13590. dspCLInit
  13591.                                        routine.
  13592.  
  13593. remoteCID                   The identification number of the remote connection
  13594. end. You
  13595.                                        must pass this value to the dspOpen
  13596.                                        routine when you open
  13597.                                        the connection or to the dspCLDeny
  13598.                                        routine when you deny
  13599.                                        the connection request.
  13600.  
  13601. remoteAddress          The internet address of the remote socket that sent a
  13602. request to
  13603.                                        open a connection. This address consists
  13604.                                        of a 2-byte network
  13605.                                        number, a 1byte node ID, and a 1-byte
  13606.                                        socket number. You
  13607.                                        must pass this value to the dspOpen
  13608.                                        routine when you open
  13609.                                        the connection or to the dspCLDeny
  13610.                                        routine when you deny
  13611.                                        the connection request.
  13612.  
  13613. filterAddress              The internet address of the socket from which you
  13614. will accept
  13615.                                        a connection request. The address
  13616.                                        consists of three fields: a
  13617.                                        2-byte network number, a 1-byte node ID,
  13618.                                        and a 1-byte socket
  13619.                                        number. Specify 0 for any of these fields
  13620.                                        for which you wish to
  13621.                                        impose no restrictions. If you specify a
  13622.                                        filter address of
  13623.                                        $00082500, for example, the connection
  13624.                                        listener accepts a
  13625.                                        connection request from any socket at
  13626.                                        node $25 of network
  13627.                                        $0008. 
  13628.  
  13629. sendSeq                       The sequence number of the first byte that the
  13630. local connection
  13631.                                       end will send to the remote connection
  13632.                                       end. ADSP uses this
  13633.                                       number to coordinate communications and to
  13634.                                       check for 
  13635.                                       errors. You must pass this value to the
  13636.                                       dspOpen routine when
  13637.                                       you open the connection.
  13638.  
  13639. sendWindow            The sequence number of the last byte that the remote
  13640.                                       connection end has buffer space to
  13641.                                       receive. ADSP uses this
  13642.                                       number to coordinate communications and to
  13643.                                       check for
  13644.                                       errors.  You must pass this value to the
  13645.                                       dspOpen routine
  13646.                                       when you open the connection.
  13647.  
  13648. attnSendSeq              The sequence number of the next attention packet that
  13649. the
  13650.                                       local connection end will transmit. ADSP
  13651.                                       uses this number to
  13652.                                       coordinate communications and to check for
  13653.                                       errors. You must
  13654.                                       pass this value to the dspOpen routine
  13655.                                       when you open the
  13656.                                       connection.
  13657.  
  13658.    Result codes
  13659.          noErr                     0         No error
  13660.          errState         –1278         Not a connection listener
  13661.          errAborted   –1279         Request aborted by the dspRemove routine
  13662.          errRefNum  –1280         Bad connection reference number
  13663.  
  13664. dspCLDeny 
  13665.  
  13666.    Parameter block
  13667.        ¨      16       ioResult              word         result code 
  13668.        Æ      24       ioCRefNum       word         driver reference number
  13669.        Æ      26       csCode                  word        always dspCLDeny
  13670.        Æ      32       ccbRefNum         word        reference number of CCB
  13671.        Æ      36       remoteCID           word        ID of remote connection
  13672.        end
  13673.        Æ      38       remoteAddress   long         remote internet address
  13674.  
  13675. The dspCLDeny routine is used by a connection server to inform a remote
  13676. connection end that its request to open a connection cannot be honored.
  13677.  
  13678. The ioResult parameter returns the result of the routine. If you call the
  13679. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13680. execution, and it changes the field to the actual result code when it completes
  13681. execution. The ioCRefNum parameter is the driver reference number returned by
  13682. the OpenDriver function. You must specify this number every time you call the
  13683. .DSP driver. The csCode parameter is the routine selector; it is always
  13684. dspCLDeny for this routine. The ccbRefNum parameter is the CCB reference number
  13685. for the connection listener that received the connection request. This number is
  13686. returned by the dspCLInit routine when you establish a connection listener. The
  13687. remoteCID and remoteAddress parameters specify the address and ID of the remote
  13688. connection end. These parameters are returned by the dspCLListen routine.
  13689.  
  13690.    Result codes
  13691.          noErr                        0       No error
  13692.          errState            –1278       Not a connection listener
  13693.         errAborted       –1279       Request aborted by the dspRemove routine
  13694.         errRefNum     –1280       Bad connection reference number
  13695.  
  13696. dspCLRemove 
  13697.  
  13698.    Parameter block
  13699.         ¨      16       ioResult                word         result code 
  13700.         Æ      24       ioCRefNum         word         driver reference number
  13701.         Æ      26       csCode                   word         always dspCLRemove
  13702.         Æ      32       ccbRefNum          word         reference number of CCB
  13703.         Æ      34       abort                       byte          abort
  13704.         connection listener if not 0
  13705.  
  13706. The dspCLRemove routine closes a connection end used as a connection listener.
  13707. You can release the memory you allocated for the CCB if you do not intend to
  13708. reopen the connection end. 
  13709.  
  13710. The ioResult parameter returns the result of the routine. If you call the
  13711. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13712. execution, and it changes the field to the actual result code when it completes
  13713. execution. The ioCRefNum parameter is the driver reference number returned by
  13714. the OpenDriver function. You must specify this number every time you call the
  13715. .DSP driver. The csCode parameter is the routine selector, always dspCLRemove
  13716. for this routine. The ccbRefNum parameter is the CCB reference number that was
  13717. returned by the dspCLInit routine. If the abort parameter is nonzero, ADSP
  13718. cancels any outstanding requests to send packets (such as the dspCLDeny
  13719. routine). 
  13720.  
  13721.    Result codes
  13722.           noErr                         0           No error
  13723.           errRefNum     –1280           Bad connection reference number
  13724. _______________________________________________________________________________
  13725.  
  13726. æKY Maintaining…an…ADSP…Connection
  13727. æC »Maintaining an ADSP Connection                                       AppleTalk Manager
  13728. _______________________________________________________________________________
  13729.  
  13730. Once you have established a connection end and opened a connection, you must be
  13731. able to send and receive data over the connection. You can use the routines in
  13732. this section to
  13733.  
  13734.   •  determine the status of a connection
  13735.  
  13736.   •  read bytes from the connection end’s receive queue
  13737.  
  13738.   •  write bytes to the connection end’s send queue and transmit them to the
  13739.   remote
  13740.       connection end
  13741.  
  13742.   •  send an attention message to the remote connection end
  13743.  
  13744.   •  discard all data that has been sent but not yet delivered, and reset the
  13745.       connection
  13746.  
  13747. dspStatus 
  13748.  
  13749.    Parameter block
  13750.          ¨       16        ioResult               word       result code 
  13751.          Æ       24        ioCRefNum        word       driver reference number
  13752.          Æ       26        csCode                  word       always dspStatus
  13753.          Æ       32        ccbRefNum         word      reference number of CCB
  13754.          ¨       34        statusCCB            long        pointer to CCB
  13755.          ¨       38        sendQPending    word       bytes waiting to be sent
  13756.          or 
  13757.  
  13758.  
  13759.          ¨       40        sendQFree            word      available send queue
  13760.          in bytes
  13761.          ¨       42        recvQPending     word       bytes waiting to be read
  13762.          from queue
  13763.          ¨       44        recvQFree             word      available receive
  13764.          queue in bytes 
  13765.  
  13766. The dspStatus routine returns the number of bytes waiting to be read and sent
  13767. and the space available in the send and receive queues. This routine also
  13768. returns a pointer to the CCB, which contains information about the state of the
  13769. connection end and about connection events received by the connection end. The
  13770. CCB is described in “The ADSP Connection Control Block” earlier in this chapter.
  13771.  
  13772. The ioResult parameter returns the result of the routine. If you call the
  13773. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13774. execution, and it changes the field to the actual result code when it completes
  13775. execution. The ioCRefNum parameter is the driver reference number returned by
  13776. the OpenDriver function. You must specify this number every time you call the
  13777. .DSP driver. The csCode parameter is the routine selector; it is always
  13778. dspStatus for this routine. The ccbRefNum parameter is the CCB reference number
  13779. that was returned by the dspInit routine. The statusCCB parameter returns a
  13780. pointer to the CCB.
  13781.  
  13782. The sendQPending parameter indicates the number of bytes of data in the send
  13783. queue, including 1 byte for each end-of-message (EOM) indicator in the send
  13784. queue. (ADSP counts 1 byte for each EOM, even though no actual data corresponds
  13785. to the EOM indicator.) The send queue contains all data that has been sent to
  13786. ADSP for transmission and that has not yet been acknowledged. Some of the data
  13787. in the send queue might have already been transmitted, but ADSP retains it in
  13788. the send queue until the remote connection end acknowledges its receipt in case
  13789. the data has to be retransmitted. The sendQFree parameter indicates the number
  13790. of bytes available in the send queue for additional data. 
  13791.  
  13792. The recvQPending parameter indicates the number of bytes in the receive queue,
  13793. including one byte for each EOM if the EOM bit is set in an ADSP packet header.
  13794. The receive queue contains all of the data that has been received by the
  13795. connection end but not yet read by the connection end’s client. The recvQFree
  13796. parameter indicates the number of bytes available in the receive queue for
  13797. additional data.
  13798.  
  13799.    Result codes
  13800.           noErr                            0           No error
  13801.           errRefNum        –1280           Bad connection reference number
  13802.  
  13803. dspRead 
  13804.  
  13805.    Parameter block
  13806.          ¨        16          ioResult               word          result code 
  13807.          Æ        24          ioCRefNum        word          driver reference
  13808.          number
  13809.          Æ        26          csCode                  word          always
  13810.          dspRead
  13811.          Æ        32          ccbRefNum         word         reference number of
  13812.          CCB
  13813.          Æ        34          reqCount              word         requested
  13814.          number of bytes
  13815.          ¨        36          actCount               word         actual number
  13816.          of bytes read
  13817.          Æ        38          dataPtr                   long          pointer to
  13818.          data buffer
  13819.          ¨        42          eom                        byte           1 if
  13820.          end-of-message; 0 otherwise
  13821.  
  13822. The dspRead routine reads bytes from the connection end’s receive queue and
  13823. places them in a buffer that you specify. You can continue to read bytes as long
  13824. as data is in the receive queue, even after you have called the dspClose routine
  13825. or after the remote connection end has called the dspClose or dspRemove
  13826. routines. The dspRead routine completes execution when it has read the number of
  13827. bytes you specify or when it encounters an end-of-message (that is, the last
  13828. byte of data in an ADSP packet that has the EOM bit set in the packet header).
  13829.  
  13830. You can call the dspStatus routine to determine the number of bytes remaining to
  13831. be read from the read queue, or you can continue to call the dspRead routine
  13832. until the actCount and eom parameters both return 0.
  13833.  
  13834. The ioResult parameter returns the result of the routine. If you call the
  13835. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13836. execution, and it changes the field to the actual result code when it completes
  13837. execution. The ioCRefNum parameter is the driver reference number returned by
  13838. the OpenDriver function. You must specify this number every time you call the
  13839. .DSP driver. The csCode parameter is the routine selector; it is always dspRead
  13840. for this routine. The ccbRefNum parameter is the CCB reference number that was
  13841. returned by the dspInit routine. 
  13842.  
  13843. You specify the number of bytes to read with the reqCount parameter, and you use
  13844. the dataPtr parameter to provide a pointer to the buffer into which ADSP should
  13845. place the data. ADSP returns the actual number of bytes read in the actCount
  13846. parameter. If the last byte read constitutes an EOM, ADSP sets the eom parameter
  13847.  
  13848. to 1.
  13849.  
  13850. If either end closes the connection before you call the dspRead routine, the
  13851. command reads whatever data is available and returns the actual amount of data
  13852. read in the actCount parameter. If the connection is closed and there is no data
  13853. in the receive queue, the dspRead routine returns the noErr result code with the
  13854. actCount parameter set to 0 and the eom parameter set to 0.
  13855.  
  13856.    Result codes
  13857.           noErr                          0          No error
  13858.           errFwdReset     –1275          Read terminated by forward reset
  13859.           errState              –1278          State isn’t open, closing, or
  13860.           closed
  13861.           errAborted        –1279          Request aborted by dspRemove or
  13862.           dspClose routine
  13863.           errRefNum      –1280          Bad connection reference number
  13864.  
  13865. dspWrite 
  13866.  
  13867.    Parameter block
  13868.         ¨      16       ioResult              word           result code 
  13869.         Æ      24       ioCRefNum       word          driver reference number
  13870.         Æ      26       csCode                 word          always dspWrite
  13871.         Æ      32       ccbRefNum        word          reference number of CCB
  13872.         Æ      34       reqCount             word          requested number of
  13873.         bytes
  13874.         ¨      36       actCount              word          actual number of
  13875.         bytes written
  13876.         Æ      38       dataPtr                  long           pointer to data
  13877.         buffer
  13878.         Æ      42       eom                       byte            1 if end of
  13879.         message; 0 otherwise
  13880.         Æ      43       flush                      byte            1 to send
  13881.         data now; 0 otherwise
  13882.  
  13883. The dspWrite routine writes bytes into the connection end’s send queue. The send
  13884. queue contains all data that has been sent to ADSP for transmission and that has
  13885. not yet been acknowledged. Some of the data in the send queue might have already
  13886. been transmitted, but ADSP retains it in the send queue until the remote
  13887. connection end acknowledges its receipt in case the data has to be
  13888. retransmitted. The dspWrite routine completes execution when it has copied all
  13889. of the data from the data buffer into the ADSP send queue.
  13890.  
  13891. ADSP transmits the data in the send queue when the remote connection end has
  13892. room to accept the data and one of the following conditions occurs:
  13893.  
  13894.   •  You call the dspWrite routine with the flush parameter set to a nonzero
  13895.        number.
  13896.  
  13897.   •  The number of bytes in the send queue equals or exceeds the blocking
  13898.   factor.
  13899.        (You use the sendBlocking parameter to the dspOptions routine to set the
  13900.        blocking factor.)
  13901.  
  13902.   •  The send timer expires.
  13903.  
  13904.   •  A connection event requires that the local connection end send an
  13905.        acknowledgment packet to the remote connection end.
  13906.  
  13907. The ioResult parameter returns the result of the routine. If you call the
  13908. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13909. execution, and it changes the field to the actual result code when it completes
  13910. execution. The ioCRefNum parameter is the driver reference number returned by
  13911. the OpenDriver function. You must specify this number every time you call the
  13912. .DSP driver. The csCode parameter is the routine selector; it is always dspWrite
  13913. for this routine. The ccbRefNum parameter is the CCB reference number that was
  13914. returned by the dspInit routine. 
  13915.  
  13916. You specify the number of bytes to write with the reqCount parameter, and you
  13917. use the dataPtr parameter to provide a pointer to the buffer from which ADSP
  13918. should read the data. The dspWrite routine returns the actual number of bytes
  13919. written in the actCount parameter. If the last byte written constitutes an EOM,
  13920. set the eom parameter to 1. You can also set the reqCount parameter to 0 and the
  13921. eom parameter to 1 to indicate that the last byte you sent the previous time you
  13922. called the dspWrite routine was the end of the message. The high-order bits of
  13923. the eom parameter are reserved for use by ADSP; you must leave these bits equal
  13924. to 0.
  13925.  
  13926. You can set the reqCount parameter to a value larger than the size of the send
  13927. queue. If you do so, the dspWrite routine writes as much data as it can into the
  13928. send queue, sends the data and waits for acknowledgment, and then writes more
  13929. data into the send queue until it has written the amount of data you requested.
  13930. In this case, the routine does not complete execution until it has finished
  13931. writing all of the data into the send queue. 
  13932.  
  13933. Set the flush parameter to 1 to cause ADSP to immediately transmit any data in
  13934. the send queue that has not already been transmitted. Set the flush parameter to
  13935. 0 to allow data to accumulate in the send queue until another condition occurs
  13936. that causes data to be transmitted. The high-order bits of the flush parameter
  13937. are reserved for use by ADSP; you must leave these bits equal to 0.
  13938.  
  13939.    Result codes
  13940.           noErr                        0         No error
  13941.           errState            –1278         Connection is not open
  13942.           errAborted      –1279         Request aborted by dspRemove or dspClose
  13943.           routine
  13944.           errRefNum    –1280         Bad connection reference number
  13945.  
  13946. dspAttention 
  13947.  
  13948.    Parameter block
  13949.         ¨       16        ioResult            word         result code 
  13950.         Æ       24        ioCRefNum     word         driver reference number
  13951.         Æ       26        csCode               word         always dspAttention
  13952.         Æ       32        ccbRefNum      word         reference number of CCB
  13953.         Æ       34        attnCode           word         client attention code
  13954.         Æ       36        attnSize             word         size of attention
  13955.         data in bytes
  13956.         Æ       38        attnData             long          pointer to
  13957.         attention data
  13958.  
  13959. The dspAttention routine sends an attention code and an attention message to the
  13960. remote connection end. Attention codes and attention messages can have any
  13961. meaning that your application and the application at the remote connection end
  13962. both recognize. The purpose of attention codes and messages is to allow clients
  13963. of ADSP to send messages outside the normal data stream. For example, if a
  13964. connection end on a mainframe computer is connected to several connection ends
  13965. in Macintosh computers being used as remote terminals, the mainframe computer
  13966. might wish to inform the remote terminals that all connections will be
  13967. terminated in ten minutes. The mainframe application could send an attention
  13968. message to each of the remote terminals informing them of this fact, and the
  13969. terminal emulation programs in the Macintosh computers could then display an
  13970. alert message on the screen so that the users could prepare to shut down.
  13971.  
  13972. The ioResult parameter returns the result of the routine. If you call the
  13973. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13974. execution, and it changes the field to the actual result code when it completes
  13975. execution. The ioCRefNum parameter is the driver reference number returned by
  13976. the OpenDriver function. You must specify this number every time you call the
  13977. .DSP driver. The csCode parameter is the routine selector; it is always
  13978. dspAttention for this routine. The ccbRefNum parameter is the CCB reference
  13979. number that was returned by the dspInit routine. 
  13980.  
  13981. The attnCode parameter is the attention code that you wish to send to the remote
  13982. connection end. You can use any value from $0000 through $EFFF for the attention
  13983. code. The values $F000 through $FFFF are reserved for use by ADSP. The attnSize
  13984. parameter is the size in bytes of the attention message you wish to send, and
  13985. the attnData parameter provides a pointer to the attention message. The
  13986. attention message can be any size from 0 through 570 bytes. There are no
  13987. restrictions on the content of the attention message.
  13988.  
  13989.    Result codes
  13990.           noErr                         0       No error
  13991.           errAttention    –1276       Attention message too long
  13992.           errState             –1278        Connection is not open
  13993.           errAborted       –1279        Request aborted by dspRemove or dspClose
  13994.           routine
  13995.           errRefNum     –1280        Bad connection reference number
  13996.  
  13997. dspReset 
  13998.  
  13999.    Parameter block
  14000.          ¨        16      ioResult           word       result code 
  14001.          Æ        24      ioCRefNum    word      driver reference number
  14002.          Æ        26      csCode              word      always dspReset
  14003.          Æ        32      ccbRefNum     word      reference number of CCB
  14004.  
  14005. The dspReset routine causes ADSP to discard all data in the send queue, all data
  14006. in transit to the remote connection end, and all data in the remote connection
  14007. end’s receive queue that the client has not yet read. This process is known as a
  14008. forward reset. ADSP then resynchronizes the connection. You can determine that
  14009. your connection end has received a forward reset and has discarded all data in
  14010. the receive queue by checking the eFwdReset flag in the userFlags field of the
  14011. CCB. The CCB is described in “The ADSP Connection Control Block” earlier in this
  14012. chapter. 
  14013.  
  14014. The ioResult parameter returns the result of the routine. If you call the
  14015. routine asynchronously, the routine sets this field to 1 as soon as it begins
  14016. execution, and it changes the field to the actual result code when it completes
  14017. execution. The ioCRefNum parameter is the driver reference number returned by
  14018. the OpenDriver function. You must specify this number every time you call the
  14019. .DSP driver. The csCode parameter is the routine selector; it is always dspReset
  14020. for this routine. The ccbRefNum parameter is the CCB reference number that was
  14021. returned by the dspInit routine. 
  14022.  
  14023.    Result codes
  14024.           noErr                         0       No error
  14025.           errState             –1278       Connection is not open
  14026.           errAborted       –1279       Request aborted by dspRemove or dspClose
  14027.           routine
  14028.           errRefNum     –1280       Bad connection reference number
  14029. _______________________________________________________________________________
  14030.  
  14031. æKY The….ENET…Driver…Volume…VI
  14032. æC »The .ENET Driver Volume VI                                           AppleTalk Manager
  14033. _______________________________________________________________________________
  14034.  
  14035. The .ENET driver is normally called by the AppleTalk Manager through the
  14036. AppleTalk connection file for EtherTalk when the user has selected EtherTalk
  14037. from the Network control panel. You can write your own protocol stack or
  14038. application that uses the .ENET driver directly, rather than through AppleTalk.
  14039. This section describes how to open the .ENET driver, how to send data to it
  14040. directly for transmission over the Ethernet network, and how to write a protocol
  14041. handler to receive data from the network. 
  14042.  
  14043. The system .ENET driver locates and opens the drivers for installed NuBus®
  14044. Ethernet cards. For each Ethernet NuBus card, the .ENET driver searches the open
  14045. resource files for a driver with a resource type of 'enet' and a resource ID
  14046. equal to the board ID of the NuBus card. If it doesn't find such a driver
  14047. resource, it then looks for a driver named .ENET in the slot resources in the
  14048. ROM of the NuBus card. See Designing Cards and Drivers for the Macntosh Family
  14049. for discussions of NuBus board IDs and slot resources.
  14050.  
  14051. _______________________________________________________________________________
  14052.  
  14053. æKY Providing…Your…Own…Ethernet…Driver
  14054. æC »Providing Your Own Ethernet Driver                                   AppleTalk Manager
  14055. _______________________________________________________________________________
  14056.  
  14057. If you write an Ethernet driver for use with your own Ethernet NuBus card, you
  14058. should provide the features and functions described in this chapter. You can
  14059. store the driver in the firmware of the NuBus card as described in Designing
  14060. Cards and Drivers for the Macntosh Family  and in the Device Manager chapter of
  14061. Inside Macintosh , Volume V, or you can provide a RAM-based driver as described
  14062. in the Device Manager chapter of Inside Macintosh , Volume II. If you place your
  14063. Ethernet driver in the ROM of the NuBus card, you must name the driver .ENET. If
  14064. you provide a RAM-based driver, you must give it a resource type of 'enet' and a
  14065. resource ID equal to the board ID of your NuBus card. The 'enet' resource type
  14066. is identical to the 'DRVR' resource type described in the Device Manager chapter
  14067. of Volume II. 
  14068.  
  14069.    Note:  You must not name a RAM-based driver “.ENET,” because doing so would
  14070.    replace the system .ENET driver. 
  14071.  
  14072. If you write an Ethernet driver for use with a non-NuBus network interface (such
  14073. as an Ethernet card for the Macintosh SE/30 or an Ethernet connection through
  14074. the SCSI port), you should provide the features and functions described in this
  14075. chapter for the .ENET driver and should name your driver .ENET0. If you do so,
  14076. any software written to use the .ENET driver should work with your driver.
  14077.  
  14078. _______________________________________________________________________________
  14079.  
  14080. æKY Changing…the…Ethernet…Hardware…Address
  14081. æC »Changing the Ethernet Hardware Address                               AppleTalk Manager
  14082. _______________________________________________________________________________
  14083.  
  14084. Each Ethernet NuBus card or other Ethernet hardware interface device contains a
  14085. unique 6-byte hardware address assigned by the manufacturer of the device. The
  14086. .ENET driver normally uses this address to determine whether to receive a
  14087. packet. To change the hardware address for your node, place in the System file a
  14088. resource of type 'eadr' with a resource ID equal to the slot number of the
  14089. Ethernet NuBus card. If the Ethernet device is not a NuBus card (it might be a
  14090. slot card in a Macintosh SE/30, for example), use a resource ID of 0. 
  14091.  
  14092. The 'eadr' resource consists only of a 6-byte number. Do not use the broadcast
  14093. address or a multicast address for this number. (The broadcast address is
  14094. $FF-FF-FF-FF-FF-FF. A multicast address is any Ethernet address in which the
  14095. low-order bit of the high-order byte is set to 1.) When you open the .ENET
  14096. driver, it looks for an 'eadr' resource. If it finds one, the driver substitutes
  14097. the number in this resource for the Ethernet hardware address and uses it until
  14098. the driver is closed or reset. 
  14099.  
  14100.    Note:  To avoid address collisions, you should never arbitrarily change the
  14101.    Ethernet hardware address. This feature should be used only by a system
  14102.    administrator who can keep track of all the Ethernet addresses in the system.
  14103.  
  14104. _______________________________________________________________________________
  14105.  
  14106. æKY Opening…the….ENET…Driver
  14107. æC »Opening the .ENET Driver                                             AppleTalk Manager
  14108. _______________________________________________________________________________
  14109.  
  14110. Before you use the OpenSlot function to open the .ENET driver, you must
  14111. determine which NuBus slots contain EtherTalk cards. The OpenSlot function is
  14112. described in the Device Manager chapter of Volume V. Use the SGetTypesRsrc
  14113. function described in the Slot Manager chapter of this volume to determine which
  14114. NuBus slots contain EtherTalk cards. To find EtherTalk NuBus cards, use the
  14115. value catNetwork in the field spCategory of the GetTypesRsrc function parameter
  14116. block, and use the value typEtherNet in the field spCType. If you cannot find
  14117. any EtherTalk NuBus cards, you should also attempt to open the .ENET0 driver in
  14118. case a non-NuBus EtherTalk card is attached to the system. You should provide a
  14119. user interface that allows the user to select a specific EtherTalk card in the
  14120. case that more than one is present.
  14121.  
  14122. Listing 32-7 illustrates the use of the GetTypesRsrc function and the OpenSlot
  14123. function to open the .ENET driver.
  14124.  
  14125. ¿ Listing 32-7   Finding an EtherTalk card and opening the .ENET driver
  14126.  
  14127. VAR
  14128.    mySBlk:      SpBlock;
  14129.    myPBRec:     ParamBlockRec;
  14130.    myErr:       OSErr;
  14131.    Found:       Integer;
  14132.    EnetStr:     Str15;
  14133.    Enet0Str:    Str15;
  14134.    myRefNum:    Integer;
  14135.  
  14136. BEGIN
  14137.    Found := 0;              {assume no sResource found}
  14138.    EnetStr := '.ENET';
  14139.    Enet0Str := '.ENET0';
  14140.  
  14141.    REPEAT
  14142.       WITH mySBlk DO
  14143.       BEGIN
  14144.           spParamData := 1;  {include search of disabled resources. }
  14145.                              { Start searching from spSlot and search }
  14146.                              { the slots above it as well.}
  14147.           spCategory := catNetwork;
  14148.           spCType := typeEtherNet;
  14149.           spDrvrSW := 0;
  14150.           spDrvrHW := 0;
  14151.           spTBMask := 3;     {match only Category and CType fields}
  14152.           spSlot := 0;       {start search from here}
  14153.           spID := 0;         {start search from here}
  14154.           spExtDev :=  0;    {ID of the external device}
  14155.       END;
  14156.       myErr := SGetTypeSRsrc(@mySBlk);
  14157.       IF myErr = noErr THEN
  14158.       {We found an sResource match, save it for later. }
  14159.       BEGIN
  14160.          Found := Found + 1;
  14161.          SaveSInfo(@mySBlk);
  14162.       END;
  14163.    UNTIL myErr = smNoMoresRsrcs;
  14164.  
  14165.    IF Found > 1 THEN
  14166.    BEGIN
  14167.       {If you found more than one sResource, put up a dialog box }
  14168.       { and let the user choose one. If any of the sResources you }
  14169.       { found were disabled, let the user know they are not available. }
  14170.       DisplaySInfo(@mySBLk);
  14171.    END;
  14172.  
  14173.    IF Found <> 0 THEN
  14174.    BEGIN  
  14175.       WITH myPBRec DO
  14176.       BEGIN
  14177.          ioCompletion := NIL;
  14178.          ioNamePtr := @EnetStr;
  14179.          ioMix := NIL;      {reserved}
  14180.          ioFlags := 0;      {single device sResource}
  14181.          ioSlot := mySBlk.spSlot;
  14182.          ioID := mySBlk.spID;
  14183.       END;
  14184.       myErr := OpenSlot(@myPBRec, FALSE);    {go open this}
  14185.    END
  14186.    ELSE myErr := OpenDriver(Enet0Str, myRefNum);
  14187.    IF myErr <> NoErr THEN DoError(myErr);
  14188. END;
  14189. _______________________________________________________________________________
  14190.  
  14191. æKY Using…a…Write-Data…Structure…to…Transmit…Ethernet…Data
  14192. æC »Using a Write-Data Structure to Transmit Ethernet Data               AppleTalk Manager
  14193. _______________________________________________________________________________
  14194.  
  14195. When you use the EWrite function to send data to the .ENET driver for
  14196. transmission over the Ethernet network, you provide a pointer to a write-data
  14197. structure (Figure 32-5). A write-data structure contains a series of pairs of
  14198. length words and pointers. Each pair indicates the length and location of a
  14199. portion of the data that constitutes the packet to be sent over the network. The
  14200. first length-pointer pair points to a 14-byte header block, which starts with
  14201. the destination node hardware address. Note that this is not the AppleTalk
  14202. address, but is the hardware address of the destination node. If you are calling
  14203. the .ENET driver directly, you must obtain the Ethernet address of the
  14204. destination node yourself; AppleTalk cannot provide it. 
  14205.  
  14206. The next 6 bytes of the header block are reserved for use by the .ENET driver.
  14207. These bytes are followed by the 2-byte Ethernet protocol type. Data may follow
  14208. the header block; all other length-pointer pairs point to data. The write-data
  14209. structure terminates with a 0 word.
  14210.  
  14211. ¿ Figure 32-5   An Ethernet write-data structure ø 
  14212.  
  14213. When you first open the .ENET driver, it allocates a 768-byte buffer that it
  14214. uses for transmitting data packets. This buffer is large enough to hold the
  14215. largest EtherTalk packet, which is 621 bytes in size. If you want to transmit
  14216. data packets larger than 768 bytes, call the ESetGeneral function. The .ENET
  14217. driver then allocates a large enough data buffer to send packets up to 1514
  14218. bytes in size.
  14219.  
  14220. Listing 32-8 defines an Ethernet write-data structure and then calls the EWrite
  14221. function to send a data packet over Ethernet.
  14222.  
  14223. ¿ Listing 32-8   Sending a data packet over Ethernet
  14224.  
  14225. CONST
  14226.    size1  =  100;
  14227.    size2  =  333;
  14228.   
  14229. TYPE
  14230.    WDS  =  RECORD                  {write-data structure}
  14231.            length : Integer;       {length of nth entry}
  14232.            aptr : Ptr;             {pointer to nth entry}
  14233.         END;
  14234.  
  14235. VAR
  14236.    myWDS:  ARRAY [1..4] OF WDS;
  14237.    myPB:    EParamBlock;           {.ENET parameter block}
  14238.    wheader:  ARRAY [1..14] OF Byte;
  14239.    stuff1:  ARRAY [1..size1] OF Byte;
  14240.    stuff2:  ARRAY [1..size2] OF Byte;
  14241.    myErr:  OSErr;  
  14242.   
  14243. BEGIN
  14244.    {set up the write header}
  14245.    wheader[1] := $02;              {dest node ID}
  14246.    wheader[2] := $60;
  14247.    wheader[3] := $8C;
  14248.    wheader[4] := $04;
  14249.    wheader[5] := $05;
  14250.    wheader[6] := $06;
  14251.                                    {bytes 7-12 are reserved}
  14252.    wheader[13] := $08;             {protocol type}
  14253.    wheader[14] := $00;
  14254.   
  14255.    myWDS[1].length := 14;          {the write header is always 14 bytes}
  14256.    myWDS[1].aptr := @wheader;
  14257.    myWDS[2].length := size1;
  14258.    myWDS[2].aptr := @stuff1;
  14259.    myWDS[3].length := size2;
  14260.    myWDS[3].aptr := @stuff2;
  14261.    myWDS[4].length := 0;           {terminator}
  14262.  
  14263.    myPB.ePointer := @myWDS;        {pointer to write data structure}
  14264.    myErr := EWrite(@myPB, FALSE);  {send something}
  14265.    IF myErr <> NoErr THEN DoError(myErr);
  14266. END;
  14267. _______________________________________________________________________________
  14268.  
  14269. æKY Using…the…Default…Ethernet…Protocol…Handler…to…Read…Data
  14270. æC »Using the Default Ethernet Protocol Handler to Read Data             AppleTalk Manager
  14271. _______________________________________________________________________________
  14272.  
  14273. When the EtherTalk Nubus card or other Ethernet hardware receives a data packet,
  14274. it generates an interrupt to the CPU. The interrupt handler in ROM determines
  14275. the source of the interrupt and calls the .ENET driver. The .ENET driver reads
  14276. the packet header to determine the protocol type of the data packet and checks
  14277. to see if any client has specified that protocol type in a call to the EAttachPH
  14278. function. If so, the client either specified a NIL pointer to a protocol
  14279. handler, or the client provided its own protocol handler. If the client
  14280. specified a NIL pointer, the .ENET driver uses its default protocol handler to
  14281. read the data. If no one has specified that protocol type in a call to the
  14282. EAttachPH function, the .ENET driver discards the data. The EAttachPH function
  14283. is described in “Attaching and Detaching an Ethernet Protocol Handler” later in
  14284. this chapter.
  14285.  
  14286. The default protocol handler checks for an ERead function pending execution and
  14287. places the entire packet—including the packet header—into the buffer specified
  14288. by that function. The function returns the number of bytes actually read. If the
  14289. packet is larger than the data buffer, the ERead function places as much of the
  14290. packet as will fit into the buffer and returns the buf2SmallErr result code.
  14291.  
  14292. Call the ERead function asynchronously to await the next data packet. When the
  14293. .ENET driver receives the data packet, it completes execution of the ERead
  14294. function and calls your completion routine. Your completion routine should call
  14295. the ERead function again so that an ERead function is always pending execution.
  14296. If the .ENET driver receives a data packet with a protocol type for which you
  14297. specified the default protocol handler while no ERead function is pending, the
  14298. .ENET driver discards the packet.
  14299.  
  14300. You can have several asynchronous calls to the ERead function pending execution
  14301. simultaneously as long as you use different buffers and a different parameter
  14302. block for each call.
  14303.  
  14304. Listing 32-9 calls the EAttachPH function to specify that the .ENET driver
  14305. should use the default protocol handler to process protocol type MyPType. The
  14306. listing includes a completion routine that processes a received data packet and
  14307. then makes an asynchronous call to the ERead function to await the next incoming
  14308. data packet. 
  14309. In practice, you should call the EAttachPH function very early, during your
  14310. program initialization sequence, if possible. As soon as the connection is
  14311. established and you are expecting data, you should call the ERead function
  14312. asynchronously. When the .ENET driver receives a packet, it then calls your
  14313. completion routine, which should process the packet and queue another
  14314. asynchronous call to the ERead function to await the next packet. 
  14315.  
  14316. ¿ Listing 32-9   Using the default Ethernet protocol handler to read data
  14317.  
  14318. CONST
  14319.    BigBytes = 8888;
  14320.  
  14321. VAR
  14322.    myPB:     EParamBlock;
  14323.    EPBPtr:   EParamBlkPtr;
  14324.    APtr:     Ptr;
  14325.    myErr:    OSErr;  
  14326.  
  14327.    PROCEDURE MyCompRoutine;
  14328.  
  14329.    VAR
  14330.       myErr:  OSErr;  
  14331.   
  14332.    BEGIN
  14333.    {If this gets called, an incoming packet with the specified protocol }
  14334.    { type is here.}
  14335.   
  14336.       ProcessData(BigBytes, APtr);           {do something with the data}
  14337.       IF EPBPtr^.ioResult <> noErr THEN DoError(myErr);
  14338.   
  14339.       {call ERead again}
  14340.       WITH EPBPtr^ DO                        {set up ERead parameters}
  14341.       BEGIN
  14342.          ioCompletion := @MyCompRoutine;     {pointer to completion routine}
  14343.          eProtType := 77;                    {protocol type}
  14344.          ePointer := APtr;                   {pointer to read data area}
  14345.          eBuffSize := BigBytes;              {size of read data area}
  14346.       END;
  14347.       myErr := ERead(EPBPtr, TRUE);          {call ERead to wait for }
  14348.                                              { the next packet}
  14349.       IF myErr <> noErr THEN DoError(myErr);  
  14350.    END;
  14351.  
  14352. BEGIN  {main}
  14353.    EPBPtr := @myPB;
  14354.    WITH EPBPtr^ DO                        {set up EAttachPH parameters}
  14355.    BEGIN
  14356.       eProtType := 77;                    {protocol type}
  14357.       ePointer := NIL;                    {use default protocol handler}
  14358.    END;  
  14359.    myErr := EAttachPH(EPBPtr, FALSE);     {tell .ENET about this }
  14360.                                           { protocol handler}
  14361.    IF myErr <> NoErr THEN DoError(myErr);
  14362.   
  14363.    APtr := NewPtr(BigBytes);
  14364.    WITH EPBPtr^ DO                        {set up ERead parameters}
  14365.    BEGIN
  14366.       ioCompletion := @MyCompRoutine;     {pointer to completion routine}
  14367.       eProtType := 77;                    {protocol type}
  14368.       ePointer := APtr;                   {pointer to read data area}
  14369.       eBuffSize := BigBytes;              {size of read data area}
  14370.    END;
  14371.    myErr := ERead(EPBPtr, TRUE);          {wait for your packet and }
  14372.                                           { then read it}
  14373.    IF myErr <> noErr THEN DoError(myErr);
  14374.   
  14375.    {application-defined tasks}
  14376.   
  14377. END;  {main}
  14378.  
  14379. _______________________________________________________________________________
  14380.  
  14381. æKY Using…Your…Own…Ethernet…Protocol…Handler…to…Read…Data
  14382. æC »Using Your Own Ethernet Protocol Handler to Read Data                AppleTalk Manager
  14383. _______________________________________________________________________________
  14384.  
  14385. If a client of the .ENET driver has used the EAttachPH function to provide a
  14386. pointer to its own protocol handler, the .ENET driver calls that protocol
  14387. handler, which must in turn call the .ENET driver’s ReadPacket and ReadRest
  14388. routines to read the data. Your protocol handler calls the .ENET driver’s
  14389. ReadPacket and ReadRest routines in essentially the same way as you call the
  14390. .MPP drivers ReadPacket and ReadRest routines (see the AppleTalk Manager chapter
  14391. of Volume II). The following sections describe how the .ENET driver calls a
  14392. custom protocol handler and the ReadPacket and ReadRest routines.
  14393.  
  14394.    Note:  Because an Ethernet protocol handler must read from and write to the
  14395.    CPU’s registers, you cannot write a protocol handler in Pascal. 
  14396.  
  14397. _______________________________________________________________________________
  14398.  
  14399. æKY How…the….ENET…Driver…Calls…Your…Protocol…Handler
  14400. æC »How the .ENET Driver Calls Your Protocol Handler                     AppleTalk Manager
  14401. _______________________________________________________________________________
  14402.  
  14403. You can provide an Ethernet protocol handler for a particular protocol type and
  14404. use the EAttachPH function to attach it to the .ENET driver. When the driver
  14405. receives an Ethernet packet, it reads the packet header into an internal buffer,
  14406. reads the protocol type, and calls the protocol handler for that protocol type.
  14407. The CPU is in interrupt mode, and the registers are used as follows:
  14408.  
  14409. Registers on call to Ethernet protocol handler
  14410.  
  14411. A0                            Reserved for internal use by the .ENET driver. You
  14412. must 
  14413.                                  preserve this register until after the ReadRest
  14414.                                  routine has
  14415.                                  completed execution.
  14416.  
  14417. A1                           Reserved for internal use by the .ENET driver. You
  14418. must
  14419.                                 preserve this register until after the ReadRest
  14420.                                 routine has
  14421.                                 completed execution.
  14422.  
  14423. A2                           Free for your use.
  14424.  
  14425. A3                           Pointer to first byte past data-link header bytes
  14426. (the first byte after
  14427.                                 the 2-byte protocol-type field).
  14428.  
  14429. A4                           Pointer to the ReadPacket routine. The ReadRest
  14430. routine starts 2
  14431.                                  bytes after the start of the ReadPacket
  14432.                                  routine.
  14433.  
  14434. A5                           Free for your use until after the ReadRest routine
  14435. has completed
  14436.                                  execution.
  14437.  
  14438. D0                           Free for your use.
  14439.  
  14440. D1                           Number of bytes in the Ethernet packet left to be
  14441. read (that is, the
  14442.                                  number of bytes following the Ethernet header).
  14443.  
  14444. D2                           Free for your use.
  14445.  
  14446. D3                           Free for your use.
  14447.  
  14448. If your protocol handler processes more than one protocol type, you can read the
  14449. protocol-type field in the data-link header to determine the protocol type of
  14450. the packet. The protocol-type field starts 2 bytes before the address pointed to
  14451. by the A3 register. 
  14452.  
  14453.    Note:  The source address starts 8 bytes before the address pointed to by the
  14454.    A3
  14455.    register, and the destination address starts 14 bytes before the address
  14456.    pointed to
  14457.    by the A3 register.
  14458.  
  14459. If you know that the packet contains pad bytes and you know the actual size of
  14460. the data, you can reduce the number in the D1 register by the number of pad
  14461. bytes so that the .ENET driver can keep accurate track of the number of bytes
  14462. remaining to be read. In all other circumstances, you should not change the
  14463. value in the D1 register. 
  14464.  
  14465. After you have called the ReadRest routine, you can use registers A0 through A3
  14466. and D0 through D3 for your own use, but you must preserve all other registers.
  14467. You cannot depend on having access to your application global variables.
  14468.  
  14469. _______________________________________________________________________________
  14470.  
  14471. æKY How…Your…Protocol…Handler…Calls…the….ENET…Driver
  14472. æC »How Your Protocol Handler Calls the .ENET Driver                     AppleTalk Manager
  14473. _______________________________________________________________________________
  14474.  
  14475. Your protocol handler must call the .ENET driver routines ReadPacket and
  14476. ReadRest to read the incoming data packet. You may call the ReadPacket routine
  14477. as many times as you like to read the data piece by piece into one or more data
  14478. buffers, but you must always use the ReadRest routine to read the final piece of
  14479. the data packet. The ReadRest routine restores the machine state (the stack
  14480. pointers, status register, and so forth) and checks for error conditions. 
  14481.  
  14482. Before you call the ReadPacket routine, you must allocate memory for a data
  14483. buffer and place a pointer to the buffer in the A3 register. You place the
  14484. number of bytes you want to read in the D3 register. You must not request more
  14485. bytes than remain in the data packet. 
  14486.  
  14487. To call the ReadPacket routine, execute a JSR instruction to the address in the
  14488. A4 register. The ReadPacket routine uses the registers as follows:
  14489.  
  14490. Registers on entry to the ReadPacket routine
  14491.  
  14492. A3                             Pointer to a buffer to hold the data you want to
  14493. read
  14494.  
  14495. D3                             Number of bytes to read; must be nonzero
  14496.  
  14497. Registers on exit from the ReadPacket routine
  14498.  
  14499. A0                             Unchanged
  14500.  
  14501. A1                             Unchanged
  14502.  
  14503. A2                             Unchanged
  14504.  
  14505. A3                             First byte after the last byte read into buffer
  14506.  
  14507. D0                             Changed
  14508.  
  14509. D1                             Number of bytes left to be read
  14510.  
  14511. D2                             Unchanged
  14512.  
  14513. D3                             Equals 0 if requested number of bytes were read,
  14514. nonzero if error
  14515.  
  14516. The ReadPacket routine indicates an error by clearing to 0 the zero (z) flag in
  14517. the status register. If the ReadPacket routine returns an error, you must
  14518. terminate execution of your protocol handler with an RTS instruction without
  14519. calling ReadPacket again or calling ReadRest at all.
  14520.  
  14521. Call the ReadRest routine to read the last portion of the data packet, or call
  14522. it after you have read all the data with ReadPacket routines and before you do
  14523. any other processing or terminate execution. You must provide in the A3 register
  14524. a pointer to a data buffer and must indicate in the D3 register the size of the
  14525. data buffer. If you have already read all of the data with calls to the
  14526. ReadPacket routine, you can specify a buffer of size 0.
  14527.  
  14528.     †   Warning:  If you do not call the ReadRest routine after your last call
  14529.     to the
  14530.         ReadPacket routine, the system will crash.  Ê
  14531.  
  14532. To call the ReadRest routine, execu† te a JSR instruction to an address 2 bytes
  14533. past the address in the A4 register. The ReadRest routine uses the registers as
  14534. follows:
  14535.  
  14536. Registers on entry to the ReadRest routine
  14537.  
  14538. A3                             Pointer to a buffer to hold the data you want to
  14539. read
  14540.  
  14541. D3                             Size of the buffer (word length); may be 0
  14542.  
  14543. Registers on exit from the ReadRest routine
  14544.  
  14545. A0                             Unchanged
  14546.  
  14547. A1                             Unchanged
  14548.  
  14549. A2                             Unchanged
  14550.  
  14551. A3                             Pointer to first byte after the last byte read
  14552. into buffer
  14553.  
  14554. D0                             Changed
  14555.  
  14556. D1                             Changed
  14557.  
  14558. D2                             Unchanged
  14559.  
  14560. D3                             Equals 0 if requested number of bytes were read;
  14561. less than 0 if
  14562.                                   more data was left than would fit in buffer
  14563.                                   (extra data equals –D3
  14564.                                   bytes); greater than 0 if less data was left
  14565.                                   than the size of the
  14566.                                   buffer (extra buffer space equals D3 bytes)
  14567.  
  14568. The ReadRest routine indicates an error by clearing to 0 the zero (z) flag in
  14569. the status register. 
  14570.  
  14571. You must terminate execution of your protocol handler with an RTS instruction
  14572. whether or not the ReadRest routine returns an error.
  14573.  
  14574. _______________________________________________________________________________
  14575.  
  14576. æKY .ENET…Driver…Routines
  14577. æC ».ENET Driver Routines                                                AppleTalk Manager
  14578. _______________________________________________________________________________
  14579.  
  14580. An application that uses AppleTalk Manager routines for network communications
  14581. can talk to whatever AppleTalk network the user has selected through the Network
  14582. control panel. However, you can choose to write an application that talks only
  14583. to Ethernet; in this case, your application has to address the Ethernet driver
  14584. directly. This section describes the functions that you can use to control the
  14585. .ENET driver, the Ethernet driver provided with system software version 7.0.
  14586. Each .ENET driver function is of the following form:
  14587.  
  14588. FUNCTION Efunc (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14589.  
  14590. The thePBptr parameter is a pointer to the .ENET parameter block and the async
  14591. parameter is a Boolean that specifies whether the function is to be executed
  14592. synchronously or asynchronously. Set the async parameter to TRUE to execute the
  14593. function asynchronously.
  14594.  
  14595. The .ENET parameter block is defined as follows:
  14596.  
  14597.    TYPE EParamBlock = 
  14598.         packed record
  14599.            qLink:         QElemPtr;         {next queue entry}
  14600.            qType:         Integer;          {queue type}
  14601.            ioTrap:        Integer;          {routine trap}
  14602.            ioCmdAddr:     Ptr;              {routine address}
  14603.            ioCompletion:  ProcPtr;          {completion   routine}
  14604.            ioResult:      OsErr;            {result code}
  14605.            ioNamePtr:     StringPtr;        {driver name}
  14606.            ioVRefNum:     Integer;          {volume reference number}
  14607.            ioRefNum:      Integer;          {driver reference number}
  14608.            csCode:        Integer;          {primary command code}
  14609.  
  14610.            CASE Integer OF
  14611.            ENetWrite,
  14612.            ENetAttachPH,
  14613.            ENetDetachPH,
  14614.            ENetRead,
  14615.            ENetRdCancel,
  14616.            ENetGetInfo,
  14617.            ENetSetGeneral:
  14618.            (
  14619.            eProtType:     Integer;          {Ethernet protocol type}
  14620.            ePointer:      Ptr;              {pointer; use depends on }
  14621.                                             { function}
  14622.            eBuffSize      Integer;          {buffer size}
  14623.            eDataSize      Integer           {number of bytes read}
  14624.            );
  14625.             
  14626.            ENetAddMulti,
  14627.            ENetDelMulti:
  14628.            (
  14629.            eMultiAddr:  ARRAY [0..5] of Char  {Multicast address}
  14630.            );
  14631.    END;
  14632.  
  14633. The qLink, qType, ioTrap, ioCmdAddr, ioNamePtr, and ioVRefNum fields are filled
  14634. in by the Device Manager; your application should not have to set or read these
  14635. fields. The ioResult field returns the result of the function. If you call the
  14636. function asynchronously, the function sets this field to 1 as soon as it begins
  14637. execution, and it changes the field to the actual result code when it completes
  14638. execution. The ioCompletion field is a pointer to a completion routine that you
  14639. can provide; the Device Manager calls your completion routine when it completes
  14640. execution of the function. If you are not providing a completion routine,
  14641. specify NIL for this field. You must obtain the driver reference number from the
  14642. OpenDriver function and use it for the ioRefNum field. 
  14643.  
  14644. The csCode field specifies the command to be executed; the MPW Pascal interface
  14645. fills in this field for you. The .ENET driver accepts the following constants as
  14646. routine selectors:
  14647.  
  14648. CONST  {.ENET driver routine selectors}
  14649.        ENetSetGeneral   = 253;  {Set "general" mode}
  14650.        ENetGetInfo      = 252;  {Get info}
  14651.        ENetRdCancel     = 251;  {Cancel read}
  14652.        ENetRead         = 250;  {Read}
  14653.        ENetWrite        = 249;  {Write}
  14654.        ENetDetachPH     = 248;  {Detach protocol handler}
  14655.        ENetAttachPH     = 247;  {Attach protocol handler}
  14656.        ENetAddMulti     = 246;  {Add a multicast address}
  14657.        ENetDelMulti     = 245;  {Delete a multicast address} 
  14658.  
  14659. The remaining parameters are used only for specific functions; all of these
  14660. parameters are described in the following sections.
  14661.  
  14662. For a general discussion of the use of the Ethernet driver, see “The .ENET
  14663. Driver” earlier in this chapter.
  14664.  
  14665. _______________________________________________________________________________
  14666.  
  14667. æKY Attaching…and…Detaching…an…Ethernet…Protocol…Handler
  14668. æC »Attaching and Detaching an Ethernet Protocol Handler                 AppleTalk Manager
  14669. _______________________________________________________________________________
  14670.  
  14671. The functions in this section allow you to attach a protocol handler to the
  14672. .ENET driver, to specify which protocol handler the .ENET driver is to use for
  14673. each protocol type, and to detach a protocol handler that you previously
  14674. attached. The section “Using Your Own Ethernet Protocol Handler to Read Data,”
  14675. earlier in this chapter, describes how to write and use Ethernet protocol
  14676. handlers.
  14677.  
  14678. FUNCTION EAttachPH (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14679.  
  14680.    Parameter block
  14681.         ¨      16       ioResult           word         result code 
  14682.         Æ      26       csCode              word         always ENetAttachPH
  14683.         Æ      28       eProtType        word         Ethernet protocol type
  14684.         Æ      30       ePointer            long          pointer to protocol
  14685.         handler
  14686.  
  14687. The EAttachPH function serves two purposes: you can use it to attach to the
  14688. .ENET driver your own protocol handler for a specific protocol type, or you can
  14689. use it to specify that the .ENET driver should use the default protocol handler
  14690. for a particular protocol type. If you attach your own protocol handler, the
  14691. .ENET driver calls that protocol handler each time it receives a packet with the
  14692. protocol type you specified. If you specify that the .ENET driver should use the
  14693. default protocol handler, then you can use the ERead command to read packets
  14694. with that protocol type. 
  14695.  
  14696. The ioResult parameter returns the result of the function. If you call the
  14697. function asynchronously, the function sets this field to 1 as soon as it begins
  14698. execution, and it changes the field to the actual result code when it completes
  14699. execution. The csCode parameter is a routine selector; it is always equal to
  14700. ENetAttachPH for this function. 
  14701.  
  14702. You specify the protocol type in the eProtType parameter and provide a pointer
  14703. to the protocol handler in the ePointer parameter. If you specify NIL for the
  14704. ePointer parameter, then the .ENET driver uses the default protocol handler for
  14705. that protocol type. Specify 0 for the eProtType parameter to attach a protocol
  14706. handler for the IEEE 802.3 protocol, which uses protocol types 0 through $5DC.
  14707.  
  14708.    Note:  The LAP Manager calls the EAttachPH function with a protocol type of 0
  14709.    and thus receives all 802.3 protocol packets. Instead of using the EAttachPH
  14710.    function to install a protocol handler for an 802.3 Ethernet protocol type,
  14711.    you
  14712.    should use the L802Attach routine. In the case of an 802.3 protocol packet,
  14713.    the
  14714.    .ENET driver passes the packet to the LAP Manager 802.2 protocol handler. If
  14715.    the
  14716.    packet has the protocol type you specified with the L802Attach routine, the
  14717.    802.2
  14718.    protocol handler passes the packet on to your protocol handler. For more
  14719.    information about IEEE 802.2 and 802.3 protocols, see “The LAP Manager 802.2
  14720.    Protocol” earlier in this chapter.
  14721.  
  14722.    Result codes
  14723.           noErr                    0           No error
  14724.           LAPProtErr     –94           Protocol handler is already attached or
  14725.           node’s protocol
  14726.                                                       table is full
  14727.  
  14728. FUNCTION EDetachPH (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14729.  
  14730.    Parameter block
  14731.             ¨       16        ioResult           word          result code 
  14732.             Æ       26        csCode              word          always
  14733.             ENetDetachPH
  14734.             Æ       28        eProtType        word         Ethernet protocol
  14735.             type
  14736.  
  14737. The EDetachPH function detaches a protocol handler from the .ENET driver. Once
  14738. you have removed a protocol type from the node’s protocol table with this
  14739. function, the .ENET driver no longer delivers packets with that protocol type.
  14740. You specify the protocol type in the eProtType parameter.
  14741.  
  14742. The ioResult parameter returns the result of the function. If you call the
  14743. function asynchronously, the function sets this field to 1 as soon as it begins
  14744. execution, and it changes the field to the actual result code when it completes
  14745. execution. The csCode parameter is a routine selector that is set automatically
  14746. for you by the MPW interface; it is always equal to ENetDetachPH for this
  14747. function. 
  14748.  
  14749. When you call the EDetachPH function, any pending calls to the ERead function
  14750. terminate with the reqAborted result code.
  14751.  
  14752.    Result codes
  14753.           noErr                        0           No error
  14754.           LAPProtErr          –94          No protocol handler is attached
  14755. _______________________________________________________________________________
  14756.  
  14757. æKY Writing…and…Reading…Ethernet…Packets
  14758. æC »Writing and Reading Ethernet Packets                                 AppleTalk Manager
  14759. _______________________________________________________________________________
  14760.  
  14761. The functions in this section send and read Ethernet packets, cancel execution
  14762. of a read operation, return information about the .ENET driver, and switch the
  14763. .ENET driver from limited-transmission mode to general-transmission mode. 
  14764.  
  14765. FUNCTION EWrite (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr; 
  14766.  
  14767.    Parameter block
  14768.         ¨       16       ioResult        word         result code 
  14769.         Æ       26       csCode           word         always ENetWrite
  14770.         Æ       30       ePointer         long          pointer to write-data
  14771.         structure
  14772.  
  14773. The EWrite function uses the .ENET driver to send a data packet over Ethernet.
  14774. You must first prepare a write-data structure that specifies the destination
  14775. address and the protocol type and contains the data that you want to send. You
  14776. place a pointer to the write-data structure in the ePointer parameter. If you
  14777. want to send a packet larger than 768 bytes, you must first call the ESetGeneral
  14778. function to put the .ENET driver in general transmission mode. If the size of
  14779. the packet you provide is less than 60 bytes, the driver adds pad bytes to the
  14780. packet. Write-data structures are described in “Using a Write-Data Structure to
  14781. Transmit Ethernet Data” earlier in this chapter.
  14782.  
  14783. The ioResult parameter returns the result of the function. If you call the
  14784. function asynchronously, the function sets this field to 1 as soon as it begins
  14785. execution, and it changes the field to the actual result code when it completes
  14786. execution. The csCode parameter is a routine selector that is set automatically
  14787. for you by the MPW interface; it is always equal to ENetWrite for this function.
  14788.  
  14789.  
  14790.    Result codes
  14791.           noErr                       0          No error
  14792.           eLenErr               –92          Packet too large or first entry of
  14793.           the
  14794.                                                         write-data-structure did
  14795.                                                         not contain the full
  14796.                                                         14-byte
  14797.                                                         header
  14798.           excessCollsns     –95          Hardware error
  14799.  
  14800. FUNCTION ERead (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14801.  
  14802. Parameter block
  14803.       ¨       16       ioResult             word              result code 
  14804.       Æ       26       csCode                word              always ENetRead
  14805.       Æ       28       eProtType          word              Ethernet protocol
  14806.       type
  14807.       Æ       30       ePointer              long              pointer to data
  14808.       buffer
  14809.       Æ       34       eBuffSize            word            size of data buffer
  14810.       ¨       36       eDataSize           word             number of bytes read
  14811.  
  14812. The ERead function uses the default protocol handler to read a data packet and
  14813. place it in a data buffer. You can use the ERead function to read packets of a
  14814. particular protocol type only after you have used the EAttachPH function to
  14815. specify a NIL pointer to the protocol handler for that protocol type.
  14816.  
  14817. The ioResult parameter returns the result of the function. If you call the
  14818. function asynchronously, the function sets this field to 1 as soon as it begins
  14819. execution, and it changes the field to the actual result code when it completes
  14820. execution. The csCode parameter is the routine selector, automatically set by
  14821. the MPW interface. It is always ENetRead for this function. 
  14822.  
  14823. The eProtType parameter specifies the protocol type of the packet you want to
  14824. read. The ePointer parameter is a pointer to the data buffer into which you want
  14825. to read data, and the eBuffSize parameter indicates the size of the data buffer.
  14826. If you are expecting EtherTalk data packets, the buffer should be at least 621
  14827. bytes in size; if you are expecting general Ethernet data packets, the buffer
  14828. should be at least 1514 bytes in size. 
  14829.  
  14830. The ERead function places the entire packet, including the packet header, into
  14831. your buffer. The function returns in the eDataSize parameter the number of bytes
  14832. actually read. If the packet is larger than the data buffer, the ERead function
  14833. places as much of the packet as will fit into the buffer and returns the
  14834. buf2SmallErr result code.
  14835.  
  14836. Call the ERead function asynchronously to await the next data packet. When the
  14837. .ENET driver receives the data packet, it completes execution of the ERead
  14838. function and calls your completion routine. If the .ENET driver receives a data
  14839. packet with a protocol type for which you specified the default protocol handler
  14840. while no ERead command is pending, the driver discards the data packet.
  14841.  
  14842. You can have several asynchronous calls to the ERead function pending execution
  14843. simultaneously, as long as you use a different parameter block for each call.
  14844.  
  14845.    Result codes
  14846.           noErr                            0         No error
  14847.           LAPProtErr             –94         Protocol not attached or protocol
  14848.           handler pointer
  14849.                                                             was not 0
  14850.           buf2SmallErr       –3101        Packet too large for buffer; partial
  14851.           data returned
  14852.           reqAborted           –1105        ERdCancel or EDetachPH function
  14853.           called
  14854.  
  14855. FUNCTION ERdCancel (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14856.  
  14857.    Parameter block
  14858.        ¨       16       ioResult         word          result code 
  14859.        Æ       26       csCode            word          always ENetRdCancel
  14860.        Æ       30       ePointer         long           pointer to ERead
  14861.        parameter block
  14862.  
  14863. The ERdCancel function cancels execution of a specific call to the ERead
  14864. function. You must have called the ERead function asynchronously to use the
  14865. ERdCancel function. You specify in the ePointer parameter a pointer to the
  14866. parameter block that you used when you called the ERead function. 
  14867.  
  14868. The ioResult parameter returns the result of the function. If you call the
  14869. function asynchronously, the function sets this field to 1 as soon as it begins
  14870. execution, and it changes the field to the actual result code when it completes
  14871. execution. The csCode parameter is the routine selector, automatically set by
  14872. the MPW interface. It is always ENetRdCancel for this function. 
  14873.  
  14874. When you call the ERdCancel function, the pending ERead function that you cancel
  14875. receives the reqAborted result code.
  14876.  
  14877.    Result codes
  14878.           noErr                          0              No error
  14879.           cbNotFound      –1102             ERead not active
  14880.  
  14881. FUNCTION EGetInfo (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14882.  
  14883.    Parameter block
  14884.         ¨           16         ioResult          word          result code 
  14885.         Æ     26         csCode             word          always ENetGetInfo
  14886.         Æ     30         ePointer           long          pointer to buffer
  14887.         Æ     34         eBuffSize         word         size of buffer
  14888.  
  14889. The EGetInfo function returns information about the .ENET driver. Before calling
  14890. this function, you must allocate a data buffer of at least 18 bytes. Put a
  14891. pointer to the buffer in the ePointer parameter and the size of the buffer in
  14892. the eBuffSize parameter.
  14893.  
  14894. The EGetInfo function places the following information in the data buffer:
  14895.  
  14896.    Bytes               Information
  14897.  
  14898.    1–6                   Ethernet address of the node on which the driver is
  14899.    installed
  14900.    7–10                 Number of times the receive queue has overflowed
  14901.    11–14               Number of data transmission operations that have timed
  14902.    out 
  14903.    15–18               Number of packets received that contain an incorrect
  14904.    address 
  14905.  
  14906. An incorrect Ethernet address is one that is neither the broadcast address, a
  14907. multicast address for which this node is registered, nor the node’s data link
  14908. address. A node could receive an incorrect Ethernet address due to a hardware or
  14909. software error.
  14910.  
  14911. The ioResult parameter returns the result of the function. If you call the
  14912. function asynchronously, the function sets this field to 1 as soon as it begins
  14913. execution, and it changes the field to the actual result code when it completes
  14914. execution. The csCode parameter is the routine selector, automatically set by
  14915. the MPW interface. It is always ENetGetInfo for this function.  
  14916.  
  14917.    Result code
  14918.           noErr         0          No error
  14919.  
  14920. FUNCTION ESetGeneral (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14921.  
  14922.    Parameter block
  14923.          ¨      16        ioResult        word           result code 
  14924.          Æ      26        csCode           word           always ENetSetGeneral
  14925.  
  14926. The ESetGeneral function switches the .ENET driver from limited-transmission
  14927. mode to general-transmission mode. In limited-transmission mode, the .ENET
  14928. driver allocates a write-data buffer of 768 bytes. This buffer size is more than
  14929. sufficient to hold an EtherTalk data packet, which can be no larger than 621
  14930. bytes. In general-transmission mode, the .ENET driver can transmit an Ethernet
  14931. data packet of up to 1514 bytes.
  14932.  
  14933. The ioResult parameter returns the result of the function. If you call the
  14934. function asynchronously, the function sets this field to 1 as soon as it begins
  14935. execution, and it changes the field to the actual result code when it completes
  14936. execution. The csCode parameter is the routine selector, automatically set by
  14937. the MPW interface. It is always ENetSetGeneral for this function.  
  14938.  
  14939. There is no command to switch the .ENET driver from general-transmission mode to
  14940. limited-transmission mode. To switch back to limited-transmission mode, you have
  14941. to reset the driver by restarting the computer.
  14942.  
  14943.    Result codes
  14944.           noErr                           0             No error
  14945.           memFullErr        –108             Insufficient memory in heap
  14946. _______________________________________________________________________________
  14947.  
  14948. æKY Adding…and…Removing…Ethernet…Multicast…Addresses
  14949. æC »Adding and Removing Ethernet Multicast Addresses                     AppleTalk Manager
  14950. _______________________________________________________________________________
  14951.  
  14952. The functions in this section add or delete Ethernet multicast addresses for a
  14953. particular node. A multicast address is an Ethernet address for which the node
  14954. accepts packets just as it does for its permanently assigned Ethernet hardware
  14955. address. In a multicast address, the low-order bit of the high-order byte is set
  14956. to 1. Each node can have any number of multicast addresses, and any number of
  14957. nodes can have the same multicast address. The purpose of a multicast address is
  14958. to allow a group of Ethernet nodes to receive the same transmission
  14959. simultaneously, in a fashion similar to the AppleTalk broadcast service.
  14960.  
  14961. FUNCTION EAddMulti (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14962.  
  14963.    Parameter block
  14964.         ¨      16        ioResult                  word              result code
  14965.  
  14966.         Æ      26        csCode                     word              always
  14967.         ENetAddMulti
  14968.         Æ      28        eMultiAddr           6 bytes           multicast
  14969.         address
  14970.  
  14971. The EAddMulti function adds a multicast address to the node on which the .ENET
  14972. driver is running. 
  14973.  
  14974. You must provide (in the eMultiAddr parameter) the multicast address that you
  14975. want to use. Each time a client of the .ENET driver calls the EAddMulti function
  14976. for a particular multicast address, the driver increments a counter for that
  14977. multicast address. Each time a client of the .ENET driver calls the EDelMulti
  14978. function, the driver decrements the counter for that address. As long as the
  14979. count for a multicast address is equal to or greater than 1, the .ENET driver
  14980. accepts packets directed to that multicast address. Therefore, if any client of
  14981. the .ENET driver in the node has called the EAddMulti function for a particular
  14982. multicast address, the driver receives packets delivered to that address.
  14983.  
  14984. The ioResult parameter returns the result of the function. If you call the
  14985. function asynchronously, the function sets this field to 1 as soon as it begins
  14986. execution, and it changes the field to the actual result code when it completes
  14987. execution. The csCode parameter is the routine selector, automatically set by
  14988. the MPW interface. It is always ENetAddMulti for this function. 
  14989.  
  14990.    Result codes
  14991.           noErr                       0             No error
  14992.           eMultiErr           –91             Invalid address or table is full 
  14993.  
  14994. FUNCTION EDelMulti (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14995.  
  14996.    Parameter block
  14997.         ¨        16        ioResult              word           result code 
  14998.         Æ        26        csCode                 word           always
  14999.         ENetDelMulti
  15000.         Æ         28        eMultiAddr       6 bytes         multicast address
  15001.  
  15002. The EDelMulti function decrements the counter kept by the .ENET driver for a
  15003. particular multicast address. Each time a client of the .ENET driver calls the
  15004. EAddMulti function, the driver increments a counter for the multicast address
  15005. specified by the eMultiAddr parameter. Each time a client of the .ENET driver
  15006. calls the EDelMulti function, the driver decrements the counter for the address
  15007. specified by the eMultiAddr parameter. As long as the count for a multicast
  15008. address is equal to or greater than 1, the .ENET driver accepts packets directed
  15009. to that multicast address. When the count for an address equals 0, the driver
  15010. removes that address from the list of multicast addresses that it accepts.
  15011.  
  15012.    Note:  Because more than one client of the .ENET driver might be using a
  15013.    particular multicast address, you should call the EDelMulti function only
  15014.    once for
  15015.    each time you called the EAddMulti function.
  15016.  
  15017. The ioResult parameter returns the result of the function. If you call the
  15018. function asynchronously, the function sets this field to 1 as soon as it begins
  15019. execution, and it changes the field to the actual result code when it completes
  15020. execution. The csCode parameter is the routine selector, automatically set by
  15021. the MPW interface. It is always ENetDelMulti for this function.  
  15022.  
  15023.    Result codes
  15024.           noErr                         0                  No error
  15025.           eMultiErr              –91'                Address not found
  15026. _______________________________________________________________________________
  15027.  
  15028. æKY Summary…of…the…Appletalk…Manager…Volume…VI
  15029. æC »Summary of the Appletalk Manager Volume VI                           AppleTalk Manager
  15030. _______________________________________________________________________________
  15031.  
  15032. Click the arrow in the lower-right corner of this window to see the summary
  15033. sections of the constants, datatypes, and routines for the AppleTalk Manager.
  15034.  
  15035. _______________________________________________________________________________
  15036.  
  15037. æKY Appletalk…Manager…Constants
  15038. æC »Appletalk Manager Constants                                          AppleTalk Manager
  15039. _______________________________________________________________________________
  15040.  
  15041. const
  15042.         {AppleTalk transitions}
  15043.         ATTransOpen             = 0;    {open transition}
  15044.         ATTransClose            = 2;    {prepare-to-close transition}
  15045.         ATTransClosePrep        = 3;    {permission-to-close transition}
  15046.         ATTransCancelClose      = 4;    {cancel-close transition}
  15047.  
  15048.         {.XPP driver routine selector}
  15049.         xCall                = 246;
  15050.  
  15051.         {.XPP driver routine selector subcodes}
  15052.         zipGetLocalZones       = 5;
  15053.         zipGetZoneList         = 6;
  15054.         zipGetMyZone           = 7;
  15055.  
  15056.         {ADSP routine selectors}
  15057.         dspInit               = 255;    {create a new connection end}
  15058.         dspRemove             = 254;    {remove a connection end}
  15059.         dspOpen               = 253;    {open a connection}
  15060.         dspClose              = 252;    {close a connection}
  15061.         dspCLInit             = 251;    {create a connection listener}
  15062.         dspCLRemove           = 250;    {remove a connection listener}
  15063.         dspCLListen           = 249;    {post a listener request}
  15064.         dspCLDeny             = 248;    {deny an open-connection request}
  15065.         dspStatus             = 247;    {get status of connection end}
  15066.         dspRead               = 246;    {read data from the connection}
  15067.         dspWrite              = 245;    {write data on the connection}
  15068.         dspAttention          = 244;    {send an attention message}
  15069.         dspOptions            = 243;    {set connection end options}
  15070.         dspReset              = 242;    {forward reset the connection}
  15071.         dspNewCID             = 241;    {generate a cid for a connection end}
  15072.  
  15073.         {ADSP connection opening modes}
  15074.         ocRequest               = 1;    {request a connection with remote}
  15075.         ocPassive               = 2;    {wait for a connection request from }
  15076.                                         { remote connection end}
  15077.         ocAccept                = 3;    {accept request as delivered by
  15078.                                          listener}
  15079.         ocEstablish             = 4;    {consider connection to be open}
  15080.  
  15081.         {ADSP connection end states}
  15082.         sListening              = 1;    {for connection listeners}
  15083.         sPassive                = 2;    {waiting for a connection request
  15084.                                          from }
  15085.                                         { remote connection end}
  15086.         sOpening                = 3;    {requesting a connection with remote}
  15087.         sOpen                   = 4;    {connection is open}
  15088.         sClosing                = 5;    {connection is being torn down}
  15089.         sClosed                 = 6;    {connection end state is closed}
  15090.  
  15091.         {ADSP client event flags}
  15092.         eClosed               = $80;    {received connection closed advice}
  15093.         eTearDown             = $40;    {closed due to broken connection}
  15094.         eAttention            = $20;    {received attention message}
  15095.         eFwdReset             = $10;    {received forward reset advice}
  15096.  
  15097.         {miscellaneous ADSP constants}
  15098.         attnBufSize           = 570;    {size of client attention buffer}
  15099.         minDSPQueueSize       = 100;    {minimum size of receive or send
  15100.                                          queue}
  15101.  
  15102.          {.ENET driver values}
  15103.          catNetwork             = 4;    {spCategory for EtherTalk NB card}
  15104.          typeEtherNet           = 1;    {spCType for EtherTalk NB card}
  15105.  
  15106.          {LAP Manager values}
  15107.          LAPMgrCall             = 2;    {Offset to LAP routines}
  15108.          LAddAEQ               = 23;    {LAPAddATQ routine selector}
  15109.          LRmvAEQ               = 24;    {LAPRmvATQ routine selector}
  15110.  
  15111.          {.ENET driver routine selectors}
  15112.          ENetSetGeneral       = 253;    {Set "general" mode}
  15113.          ENetGetInfo          = 252;    {Get info}
  15114.          ENetRdCancel         = 251;    {Cancel read}
  15115.          ENetRead             = 250;    {Read}
  15116.          ENetWrite            = 249;    {Write}
  15117.          ENetDetachPH         = 248;    {Detach protocol handler}
  15118.          ENetAttachPH         = 247;    {Attach protocol handler}
  15119.          ENetAddMulti         = 246;    {Add a multicast address}
  15120.          ENetDelMulti         = 245;    {Delete a multicast address}
  15121.  
  15122. _______________________________________________________________________________
  15123.  
  15124. æKY Appletalk…Manager…Data…Types
  15125. æC »Appletalk Manager Data Types                                         AppleTalk Manager
  15126. _______________________________________________________________________________
  15127.  
  15128. TYPE ATQentry = 
  15129.      RECORD
  15130.         qLink:       ATQentryPtr;   {next queue entry}
  15131.         qType:       Integer;       {reserved}
  15132.         CallAddr:    ProcPtr;       {pointer to your routine}
  15133.      END;
  15134.      ATQentryptr = ^ATQentry;
  15135.  
  15136.      ATPParamBlock = 
  15137.      PACKED RECORD                  {extended parameter block for }
  15138.                                     { PSendRequest and PNSendRequest}
  15139.         qLink:          QElemPtr;   {next queue entry}
  15140.         qType:          Integer;    {queue type}
  15141.         ioTrap:         Integer;    {routine trap}
  15142.         ioCmdAddr:      Ptr;        {routine address}
  15143.         ioCompletion:   ProcPtr;    {completion routine}
  15144.         ioResult:       OsErr;      {result code}
  15145.         userData:       LongInt;    {ATP user bytes}
  15146.         reqTID:         Integer;    {request transaction ID}
  15147.         ioRefNum:       Integer;    {driver reference number}
  15148.         csCode:         Integer;    {primary command code}
  15149.         atpSocket:      Byte;       {currBitMap or socket number}
  15150.         atpFlags:       Byte;       {control information - set bit 2 }
  15151.                                     { for extended parameter block}
  15152.         addrBlock:      AddrBlock;  {source socket address}
  15153.         reqLength:      Integer;    {request size in bytes}
  15154.         reqPointer:     Ptr;        {pointer to request data}
  15155.         bdsPointer:     Ptr;        {pointer to response Buffer }
  15156.                                     { Data Structure}
  15157.         numOfBuffs:     Byte;       {number of responses expected}
  15158.         timeOutVal:     Byte;       {timeout interval}
  15159.         numOfResps:     Byte;       {number of responses }
  15160.                                     { actually received}
  15161.         retryCount:     Byte;       {number of retries}
  15162.         intBuff:        Integer;    {used internally for NSendRequest}
  15163.         TRelTime:       Byte        {release timer setting}
  15164.  
  15165. END;
  15166.  
  15167.      XPPParamBlock = 
  15168.      PACKED RECORD
  15169.         qLink:          QElemPtr;   {next queue entry}
  15170.         qType:          Integer;    {queue type}
  15171.         ioTrap:         Integer;    {routine trap}
  15172.         ioCmdAddr:      Ptr;        {routine address}
  15173.         ioCompletion:   ProcPtr;    {completion routine}
  15174.         ioResult:       OsErr;      {result code}
  15175.         cmdResult:      LongInt;    {command result}
  15176.         ioVRefNum:      Integer;    {volume reference number}
  15177.         ioRefNum:       Integer;    {driver reference number}
  15178.         csCode:         Integer;    {primary command code}
  15179.         CASE XPPPrmBlkType OF
  15180.           xCallParam
  15181.             xppSubCode:    Integer;  {secondary command code}
  15182.             xppTimeOut:    Byte;     {timeout period for .XPP}
  15183.             xppRetry:      Byte;     {retry count}
  15184.             filler1:       Integer;  {reserved}
  15185.             zipBuffPtr:    Ptr;      {returned zone names}
  15186.             zipNumZones:   Integer;  {number of zones returned}
  15187.             zipLastFlag:   Byte;     {nonzero when all zone }
  15188.                                      { names have been returned}
  15189.             filler2  Byte;  {reserved}
  15190.             zipInfoField: packed array[1..70] of Byte
  15191.                                      {reserved for use by .XPP}
  15192. END;
  15193. XPPParmBlkPtr = ^XPPParamBlock;
  15194.  
  15195. TRCCB = 
  15196. PACKED RECORD
  15197.    ccbLink:                TPCCB;        {link to next CCB}
  15198.    refNum:                 Integer;      {reference number}
  15199.    state:                  Integer;      {state of the connection end}
  15200.    userFlags:              Byte;         {user flags for connection}
  15201.    localSocket:            Byte;         {local socket number}
  15202.    remoteAddress:          AddrBlock;    {remote end internet address}
  15203.    attnCode:               Integer;      {attention code received}
  15204.    attnSize:               Integer;      {size of attention data}
  15205.    attnPtr:                Ptr;          {pointer to attention data}
  15206.    reserved:               PACKED ARRAY [1..220] OF Byte
  15207.                            {reserved for use by ADSP}
  15208. END;
  15209.  
  15210. AddrBlock = 
  15211. PACKED RECORD
  15212.    aNet:                   Integer;      {network number}
  15213.    aNode:                  Byte;         {node ID}
  15214.    aSocket:                Byte;         {socket number}
  15215. END;
  15216.  
  15217. DSPParamBlock = 
  15218. PACKED RECORD
  15219.    qLink:                  QElemPtr;     {next queue entry}
  15220.    qType:                  Integer;      {queue type}
  15221.    ioTrap:                 Integer;      {routine trap}
  15222.    ioCmdAddr:              Ptr;          {routine address}
  15223.    ioCompletion:           ProcPtr;      {completion routine}
  15224.    ioResult:               OsErr;        {result code}
  15225.    ioNamePtr:              StringPtr;    {reserved}
  15226.    ioVRefNum:              Integer;      {reserved}
  15227.    ioCRefNum:              Integer;      {driver reference number}
  15228.    csCode:                 Integer;      {primary command code}
  15229.    qStatus:                LongInt;      {reserved for ADSP}
  15230.    ccbRefNum:              Integer;      {CCB reference number}
  15231.  
  15232.    CASE Integer OF
  15233.    dspInit,
  15234.    dspCLInit:
  15235.    (
  15236.       ccbPtr:              TPCCB;        {pointer to CCB}
  15237.       userRoutine:         ProcPtr;      {pointer to user routine}
  15238.       sendQSize:           Integer;      {size of send queue}
  15239.       sendQueue:           Ptr;          {pointer to send queue}
  15240.       recvQSize:           Integer;      {size of receive queue}
  15241.       recvQueue:           Ptr;          {pointer to receive queue}
  15242.       attnPtr:             Ptr;          {pointer to attention- }
  15243.                                          { message buffer}
  15244.       localSocket:         Byte;         {local socket number}
  15245.       filler1:             Byte;         {filler for proper alignment}
  15246.     );
  15247.  
  15248.     dspOpen,
  15249.     dspCLListen,
  15250.     dspCLDeny:
  15251.   (
  15252.       localCID:            Integer;      {local connection ID}
  15253.       remoteCID:           Integer;      {remote connection ID}
  15254.       remoteAddress:       AddrBlock;    {remote internet address}
  15255.       filterAddress:       AddrBlock;    {address filter}
  15256.       sendSeq:             LongInt;      {send sequence number}
  15257.       sendWindow:          Integer;      {size of remote buffer}
  15258.       recvSeq:             LongInt;      {receive sequence number}
  15259.       attnSendSeq:         LongInt;      {attention send seq number}
  15260.       attnRecvSeq:         LongInt;      {attention receive seq num}
  15261.       ocMode:              Byte;         {connection opening mode}
  15262.       ocInterval:          Byte;         {interval bet open requests}
  15263.       ocMaximum:           Byte;         {retries of open conn req}
  15264.       filler2:             Byte;         {filler for proper alignment}
  15265.     );
  15266.   
  15267.     dspClose,
  15268.     dspRemove:
  15269.    (
  15270.       abort:               Byte;         {abort send requests}
  15271.       filler3:             Byte;         {filler for proper alignment}
  15272.    );
  15273.   
  15274.    dspStatus:
  15275.    (
  15276.       statusCCB:            TPCCB;       {pointer to CCB}
  15277.       sendQPending:         Integer;     {bytes waiting in send queue}
  15278.       sendQFree:            Integer;     {available send-queue buffer}
  15279.       recvQPending:         Integer;     {bytes in receive queue}
  15280.       recvQFree:            Integer;     {avail receive-queue buffer}
  15281.    )
  15282.   
  15283.    dspRead,
  15284.    dspWrite:
  15285.    (
  15286.       reqCount:             Integer;     {requested number of bytes}
  15287.       actCount:             Integer;     {actual number of bytes}
  15288.       dataPtr:              Ptr;         {pointer to data buffer}
  15289.       eom:                  Byte;        {1 if end of message}
  15290.       flush:                Byte;        {1 to send data now}
  15291.    )
  15292.   
  15293.    dspAttention:
  15294.    (
  15295.       attnCode:             Integer;     {client attention code}
  15296.       attnSize:             Integer;     {size of attention data}
  15297.       attnData:             Ptr;         {pointer to attention data}
  15298.       attnInterval:         Byte;        {reserved}
  15299.       filler4:              Byte;        {filler for proper alignment}
  15300.    )
  15301.   
  15302.    dspOptions:
  15303.    (
  15304.       sendBlocking:         Integer;     {send-blocking threshold}
  15305.       sendTimer:            Byte;        {reserved}
  15306.       rtmtTimer:            Byte;        {reserved}
  15307.       badSeqMax:            Byte;        {retransmit advice threshold}
  15308.       useCheckSum:          Byte;        {DDP checksum for packets}
  15309.    )
  15310.   
  15311.    dspNewCID:
  15312.    (
  15313.       newCID:               Integer      {new connection ID}
  15314.    )
  15315. END;
  15316.  
  15317. EParamBlock = 
  15318. PACKED RECORD
  15319.    qLink:           QElemPtr;         {next queue entry}
  15320.    qType:           Integer;          {queue type}
  15321.    ioTrap:          Integer;          {routine trap}
  15322.    ioCmdAddr:       Ptr;              {routine address}
  15323.    ioCompletion:    ProcPtr;          {completion routine}
  15324.    ioResult:        OsErr;            {result code}
  15325.    ioNamePtr:       StringPtr;        {driver name}
  15326.    ioVRefNum:       Integer;          {volume reference number}
  15327.    ioRefNum:        Integer;          {driver reference number}
  15328.    csCode:          Integer;          {primary command code}
  15329.   
  15330.    CASE Integer OF
  15331.    ENetWrite,
  15332.    ENetAttachPH,
  15333.    ENetDetachPH,
  15334.    ENetRead,
  15335.    ENetRdCancel,
  15336.    ENetGetInfo,
  15337.    ENetSetGeneral:
  15338.    (
  15339.    eProtType:       Integer;          {Ethernet protocol type}
  15340.    ePointer:        Ptr;              {pointer; use depends on }
  15341.                                       { function}
  15342.    eBuffSize        Integer;          {buffer size}
  15343.    eDataSize        Integer           {number of bytes read}
  15344.    );
  15345.    ENetAddMulti,
  15346.    ENetDelMulti:
  15347.    (
  15348.    eMultiAddr:  ARRAY [0..5] of Char  {Multicast address}
  15349.    );
  15350. END;
  15351. EParamBlkPtr = ^EParamBlock;
  15352. _______________________________________________________________________________
  15353.  
  15354. æKY Appletalk…Manager…Routines…Summary
  15355. æC »Appletalk Manager Routines Summary                                   AppleTalk Manager
  15356. _______________________________________________________________________________
  15357.  
  15358. Getting Information About the .MPP Driver
  15359.  
  15360. FUNCTION PGetAppleTalkInfo  (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  15361.  
  15362.  
  15363. Adding and Removing AppleTalk Transition Queue Entries
  15364.  
  15365. FUNCTION LAPAddATQ  (theATQEntry: ATQEntryPtr): OSErr;
  15366.  
  15367. FUNCTION LAPRmvATQ  (theATQEntry: ATQEntryPtr): OSErr;
  15368.  
  15369.  
  15370. Sending Messages to the AppleTalk Transition Queue
  15371.  
  15372. FUNCTION PATalkClosePrep  (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  15373.  
  15374.  
  15375. Defining Your Own AppleTalk Transition 
  15376.  
  15377. PROCEDURE ATEvent  (event: LongInt; infoPtr: Ptr);
  15378.  
  15379. FUNCTION ATPreFlightEvent  (event,cancel: LongInt; infoPtr: Ptr) : OSErr;
  15380.  
  15381.  
  15382. Canceling All Calls to the ATPGetRequest Function
  15383.  
  15384. FUNCTION ATPKillAllGetReq  (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  15385.  
  15386.  
  15387. Obtaining Zone Information
  15388.  
  15389. FUNCTION GetMyZone  (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  15390.  
  15391. FUNCTION GetLocalZones  (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  15392.  
  15393. FUNCTION GetZoneList  (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  15394.  
  15395.  
  15396. Attaching and Detaching an Ethernet Protocol Handler
  15397.  
  15398. FUNCTION EAttachPH  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15399.  
  15400. FUNCTION EDetachPH  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15401.  
  15402.  
  15403. Writing and Reading Ethernet Packets
  15404.  
  15405. FUNCTION EWrite  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15406.  
  15407. FUNCTION ERead  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15408.  
  15409. FUNCTION ERdCancel  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15410.  
  15411. FUNCTION EGetInfo  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15412.  
  15413. FUNCTION ESetGeneral  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15414.  
  15415.  
  15416. Adding and Removing Ethernet Multicast Addresses
  15417.  
  15418. FUNCTION EAddMulti  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15419.  
  15420. FUNCTION EDelMulti  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15421. _______________________________________________________________________________
  15422.  
  15423. æKY Appletalk…Manager…Global…Variable
  15424. æC »Appletalk Manager Global Variable                                    AppleTalk Manager
  15425. _______________________________________________________________________________
  15426.  
  15427. LapMgrPtr                  The start of the LAP Manager
  15428.  
  15429. _______________________________________________________________________________
  15430.  
  15431. æKY Appletalk…Manager…Result…Codes
  15432. æC »Appletalk Manager Result Codes                                       AppleTalk Manager
  15433. _______________________________________________________________________________
  15434.  
  15435. noErr                                0            no error
  15436. qErr                                 –1            Queue element not found
  15437. closeErr                        –24            permission to close .MPP driver
  15438. was denied
  15439. paramErr                     –50            Version number is too high
  15440. ddpSktErr                    –91            error opening socket
  15441. eMultiErr                    –91            invalid address, address not found,
  15442. or table is full 
  15443. eLenErr                        –92            packet too large or first entry of
  15444. the write-data
  15445.                                                          structure did not
  15446.                                                          contain the full
  15447.                                                          14-byte header
  15448. noBridgeErr                –93            no router is available
  15449. LAPProtErr                 –94            protocol handler is already attached,
  15450. node’s protocol 
  15451.                                                          table is full, no
  15452.                                                          protocol handler is
  15453.                                                          attached, or
  15454.                                                          protocol handler
  15455.                                                          pointer was not 0
  15456. excessCollsns             –95             hardware error
  15457. memFullErr             –108             Insufficient memory in heap
  15458. reqFailed                 –1096             request to contact router failed;
  15459. retry count exceeded 
  15460. cbNotFound           –1102             control block not found, no pending
  15461. asynchronous
  15462.                                                            calls, or ERead not
  15463.                                                            active
  15464. reqAborted               –1105             ERdCancel or EDetachPH function
  15465. called
  15466. errOpenDenied       –1273             open request denied by recipient
  15467. errDSPQueueSize   –1274             send or receive queue is too small
  15468. errFwdReset             –1275            read terminated by forward reset
  15469. errAttention             –1276            attention message too long
  15470. errOpening               –1277             attempt to open connection failed
  15471. errState                      –1278             bad connection state for this
  15472. operation
  15473. errAborted                –1279             request aborted by dspRemove or
  15474. dspClose routine
  15475. errRefNum              –1280              bad connection reference number
  15476. buf2SmallErr            –3101             packet too large for buffer; partial
  15477. data returned
  15478. _______________________________________________________________________________
  15479.  
  15480. æKY Appletalk…Manager…Assembly-language…Information
  15481. æC »Appletalk Manager Assembly-language Information                      AppleTalk Manager
  15482. _______________________________________________________________________________
  15483.  
  15484. Constants
  15485.  
  15486. ;ADSP queue element equates & size
  15487. csQStatus     .EQU      CSParam        ;adsp internal use
  15488. csCCBRef      .EQU      csQStatus+4    ;refnum of ccb
  15489.  
  15490.  
  15491. AppleTalk Transition Queue Entry Data Structure
  15492.  
  15493. AeQQLink         long             next queue entry
  15494. AeQQType        word             reserved
  15495. AeQCallAddr   long              pointer to your routine
  15496.   
  15497.  
  15498. ADSP Connection Control Block Data Structure
  15499.  
  15500. ccbLink                   long             link to next CCB
  15501. refNum                 word            reference number
  15502. state                        word            state of the connection end
  15503. userFlags                byte             user flags for connection
  15504. localSocket             byte             local socket number
  15505. remoteAddress     long             internet address of remote end
  15506. attnCode                word            attention code received
  15507. attnSize                  word           size of received attention data
  15508. attnPtr                    long             pointer to received attention data
  15509. reserved                 220 bytes     reserved
  15510.  
  15511.  
  15512. XPP Parameter Block xCallParam Variant
  15513.  
  15514.       ¨          16         ioResult                  word          result code 
  15515.       Æ          26         csCode                     word          routine
  15516.       selector; always xCall
  15517.       Æ          28         xppSubCode           word          routine selector
  15518.       subcode
  15519.       Æ          30         xppTimeOut           byte            retry interval
  15520.       in seconds
  15521.       Æ          31         xppRetry                  byte            retry
  15522.       count
  15523.       Æ          34         zipBuffPtr                long           pointer to
  15524.       data buffer
  15525.       ¨          38         zipNumZones       word          number of names
  15526.       returned
  15527.       ¨          40         zipLastFlag              byte            nonzero if
  15528.       no more names
  15529.       Æ          42         zipInfoField             70 bytes     for use by
  15530.       ZIP; first word set to 0
  15531.  
  15532.  
  15533. Parameter Block for dspInit and dspCLInit
  15534.  
  15535.      ¨       16      ioResult             word         result code 
  15536.      Æ       24      ioCRefNum      word         driver reference number
  15537.      Æ       26      csCode                word         dspInit or dspCLInit
  15538.      ¨       32      ccbRefNum       word         reference number of CCB
  15539.      Æ       34      ccbPtr                   long          pointer to CCB
  15540.      Æ       38      userRoutine      long          pointer to routine to call
  15541.      on 
  15542.  
  15543.                                                                          events
  15544.      Æ       42      sendQSize          word         size in bytes of the send
  15545.      queue
  15546.      Æ       44      sendQueue         long          pointer to send queue
  15547.      Æ       48      recvQSize           word         size in bytes of the
  15548.      receive queue
  15549.      Æ       50      recvQueue          long          pointer to receive queue
  15550.      Æ       54      attnPtr                  long          pointer to buffer
  15551.      for incoming 
  15552.  
  15553.  
  15554.  
  15555.      ´       58      localSocket          byte           DDP socket number for
  15556.      this 
  15557.  
  15558.                                                                           end
  15559.  
  15560.  
  15561. Parameter Block for dspOptions
  15562.  
  15563.       ¨       16       ioResult             word          result code 
  15564.       Æ       24       ioCRefNum      word         driver reference number
  15565.       Æ       26       csCode                 word         always dspOptions
  15566.       Æ       32       ccbRefNum        word         reference number of CCB
  15567.       Æ       34       sendBlocking     word         send-blocking threshold
  15568.       Æ       38       badSeqMax          byte           threshold to send
  15569.       retransmit advice
  15570.       Æ       39       useCheckSum    byte           use DDP checksum?
  15571.  
  15572.  
  15573. Parameter Block for dspOpen, dspCLListen, and dspCLDeny
  15574.  
  15575.       ¨       16        ioResult              word         result code 
  15576.       Æ       24        ioCRefNum       word         driver reference number
  15577.       Æ       26         csCode                word         dspOpen,
  15578.       dspCLListen, or 
  15579.  
  15580.  
  15581.       Æ       32        ccbRefNum        word         reference number of CCB
  15582.       ¨       34        localCID              word         ID of this connection
  15583.       end
  15584.       ´       36        remoteCID          word        ID of remote connection
  15585.       end
  15586.       ´       38        remoteAddress   long         remote internet address
  15587.       Æ       42        filterAddress       long         filter for open
  15588.       connection requests
  15589.       ´       46        sendSeq                long         initial send
  15590.       sequence number
  15591.       ´       50        sendWindow     word        initial size of remote
  15592.       receive queue
  15593.       Æ       52        recvSeq                 long         initial receive
  15594.       sequence number
  15595.       ´       56        attnSendSeq         long        attention send sequence
  15596.       number
  15597.       Æ       60        attnRecvSeq         long        attention receive
  15598.       sequence number
  15599.       Æ       64        ocMode                 byte          connection-opening
  15600.       mode
  15601.       Æ       65        ocInterval             byte         interval between
  15602.       open requests
  15603.       Æ       66        ocMaximum        byte         retries of open-connection
  15604.       request
  15605.  
  15606.  
  15607. Parameter Block for dspNewCID
  15608.  
  15609.       ¨       16        ioResult              word           result code 
  15610.       Æ       24        ioCRefNum       word           driver reference number
  15611.       Æ       26        csCode                 word            always dspNewCID
  15612.       Æ       32        ccbRefNum        word           reference number of CCB
  15613.       ¨       34        newCID               word           ID of new connection
  15614.  
  15615.  
  15616. Parameter Block for dspClose, dspRemove, and dspCLRemove, and dspCLRemove
  15617.  
  15618.       ¨       16        ioResult               word        result code 
  15619.       Æ       24        ioCRefNum        word        driver reference number
  15620.       Æ       26        csCode                  word        dspClose, dspRemove,
  15621.       or 
  15622.  
  15623.  
  15624.       Æ       32        ccbRefNum         word        reference number of CCB
  15625.       Æ       34        abort                      byte          abort send
  15626.       requests or connection 
  15627.  
  15628.                                                                             if
  15629.                                                                             not
  15630.                                                                             0
  15631.  
  15632.  
  15633. Parameter Block for dspStatus
  15634.  
  15635.       ¨       16        ioResult               word              result code 
  15636.       Æ       24        ioCRefNum        word              driver reference
  15637.       number
  15638.       Æ       26        csCode                  word              always
  15639.       dspStatus
  15640.       Æ       32        ccbRefNum        word               reference number of
  15641.       CCB
  15642.       ¨       34        statusCCB            pointer          pointer to CCB
  15643.       ¨       38        sendQPending   word               bytes waiting to be
  15644.       sent or 
  15645.                                                                                
  15646.  
  15647.       ¨       40        sendQFree           word             available send
  15648.       queue in bytes
  15649.       ¨       42        recvQPending    word              bytes waiting to be
  15650.       read from queue
  15651.       ¨       44        recvQFree            word             available receive
  15652.       queue in bytes 
  15653.  
  15654.  
  15655. Parameter Block for dspRead and dspWrite
  15656.  
  15657.       ¨       16        ioResult            word           result code 
  15658.       Æ       24        ioCRefNum     word           driver reference number
  15659.       Æ       26        csCode               word           dspRead or dspWrite
  15660.       Æ       32        ccbRefNum      word           reference number of CCB
  15661.       Æ       34        reqCount          word           requested number of
  15662.       bytes
  15663.       ¨       36        actCount           word           actual number of bytes
  15664.       read or 
  15665.  
  15666.  
  15667.       Æ       38        dataPtr             pointer        pointer to data
  15668.       buffer
  15669.       ¨       42        eom                  byte              1 if
  15670.       end-of-message; 0 otherwise
  15671.       Æ       43        flush                 byte              1 to send data
  15672.       now; 0 otherwise
  15673.  
  15674.  
  15675. Parameter Block for dspAttention and dspReset
  15676.  
  15677.       ¨       16        ioResult              word            result code 
  15678.       Æ       24        ioCRefNum      word            driver reference number
  15679.       Æ       26        csCode                word            dspAttention or
  15680.       dspReset
  15681.       Æ       32        ccbRefNum       word            reference number of CCB
  15682.       Æ       34        attnCode            word            client attention
  15683.       code
  15684.       Æ       36        attnSize              word            size of attention
  15685.       data in bytes
  15686.       Æ       38        attnData              pointer        pointer to
  15687.       attention data
  15688.  
  15689.  
  15690. .ENET Driver Parameter Block
  15691.  
  15692.     16         ¨        ioResult              word            result code 
  15693.     26         Æ        csCode                 word            routine selector
  15694.     28         Æ        eMultiAddr        6 bytes         multicast address
  15695.     28         Æ        eProtType           word            Ethernet protocol
  15696.     type
  15697.     30         Æ        ePointer              long             pointer 
  15698.     34         Æ        eBuffSize            word            size of buffer
  15699.     36         ¨        eDataSize            word           number of bytes read
  15700. _______________________________________________________________________________
  15701.  
  15702.  
  15703. æKY About…The…AppleTalkManager…Chapter
  15704. æC »ABOUT THIS CHAPTER                                       AppleTalkManager
  15705. _______________________________________________________________________________
  15706.  
  15707. The AppleTalk Manager is an interface to a pair of RAM device drivers that allow
  15708. Macintosh programs to send and receive information via an AppleTalk network. This
  15709. chapter describes the AppleTalk Manager in detail.
  15710.  
  15711. The AppleTalk Manager has been enhanced through the implementation of new protocols
  15712. and an increase in the functionality of the existing interface.
  15713.  
  15714. Reader’s guide:  The AppleTalk Manager provides services that allow Macintosh
  15715.                  programs to interact with clients in devices connected to an
  15716.                  AppleTalk network.  Hence you need the information in this
  15717.                  chapter only if your application uses AppleTalk.
  15718.  
  15719. The following is a brief summary of the changes that have been made to the AppleTalk
  15720. Manager interface.
  15721.  
  15722.   •  New parameter block–style Pascal calls have been added for the entire
  15723.      AppleTalk Manager.  These new calls give the application programmer
  15724.      better control of AppleTalk operation within an application.
  15725.   •  At open time, the .MPP driver can be told to pick a node number in
  15726.      the server range.  This is a more time consuming but more thorough
  15727.      operation than is selecting a node number in the workstation range,
  15728.      and it is required for devices acting as servers.
  15729.   •  Multiple concurrent NBP requests are now supported (just as multiple
  15730.      concurrent ATP requests have been supported).  The KillNBP command
  15731.      has been implemented to abort an outstanding NBP request.
  15732.   •  ATP requests can now be sent through client-specified sockets, instead
  15733.      of having ATP pick the socket itself.
  15734.   •  The ability to send packets to one’s own node is supported (although
  15735.      this functionality is, in the default case, disabled).
  15736.   •  Two new ATP abort calls have been added: KillSendReq and KillGetReq.
  15737.      KillSendReq is functionally equivalent to RelTCB, although its
  15738.      arguments are different.  KillGetReq is a new call for aborting
  15739.      outstanding GetRequests.
  15740.   •  Additional machine-dependent resources have been added to support,
  15741.      for example, more dynamic sockets and more concurrent ATP requests. 
  15742.   •  A new protocol called the Echo Protocol (EP) is supported.
  15743.   •  A new driver, .XPP, has been added.  The .XPP driver implements the
  15744.      workstation side of the AppleTalk Session Protocol (ASP) and a small
  15745.      portion of the AppleTalk Filing Protocol.
  15746.  
  15747. To determine if your application is running on a machine that supports these enhanced
  15748. features, check the version number of the .MPP driver (at offset DCtlQueue+1 in the
  15749. Device Control Entry).  A version number of 48 (NCVersion) or greater indicates the
  15750. presence of the new drivers.
  15751.  
  15752. You should already be familiar with:
  15753.  
  15754.   •  events, as discussed in the Toolbox Event Manager chapter
  15755.   •  interrupts and the use of devices and device drivers, as described in
  15756.      the Device Manager chapter, if you want to write your own assembly-
  15757.      language additions to the AppleTalk Manager
  15758.   •  the Inside AppleTalk manual, if you want to understand AppleTalk
  15759.      protocols in detail
  15760.  
  15761. _______________________________________________________________________________
  15762.  
  15763.  
  15764. æKY AppleTalk…Protocols
  15765. æC »APPLETALK PROTOCOLS                                      AppleTalkManager
  15766. _______________________________________________________________________________
  15767.  
  15768. The AppleTalk Manager provides a variety of services that allow Macintosh programs to
  15769. interact with programs in devices connected to an AppleTalk network. This interaction,
  15770. achieved through the exchange of variable-length blocks of data (known as packets)
  15771. over AppleTalk, follows well-defined sets of rules known as protocols.
  15772.  
  15773. Although most programmers using AppleTalk needn’t understand the details of these
  15774. protocols, they should understand the information in this section—what the services
  15775. provided by the different protocols are, and how the protocols are interrelated.
  15776. Detailed information about AppleTalk protocols is available in Inside AppleTalk.
  15777.  
  15778. The AppleTalk system architecture consists of a number of protocols arranged in
  15779. layers. Each protocol in a specific layer provides services to higher-level layers
  15780. (known as the protocol’s clients) by building on the services provided by lower-level
  15781. layers. A Macintosh program can use services provided by any of the layers in order
  15782. to construct more sophisticated or more specialized services.  Figure 1 shows the
  15783. AppleTalk Protocols and their corresponding network layers.
  15784.  
  15785. The AppleTalk Manager contains the following protocols:
  15786.  
  15787.   •  AppleTalk Link Access Protocol
  15788.   •  Datagram Delivery Protocol
  15789.   •  Routing Table Maintenance Protocol
  15790.   •  Name-Binding Protocol
  15791.   •  AppleTalk Transaction Protocol
  15792.  
  15793. The following protocols have been added to the AppleTalk Manager:
  15794.  
  15795.   •  Echo Protocol
  15796.   •  AppleTalk Session Protocol (workstation side)
  15797.   •  AppleTalk Filing Protocol (small portion of the workstation side)
  15798.  
  15799. In Figure 1, the lines indicate the interaction between the protocols.  Notice that
  15800. like the Routing Table Maintenance Protocol, the Echo Protocol is not directly accessible
  15801. to Macintosh programs.
  15802.  
  15803. The details of these protocols are provided in Inside AppleTalk.
  15804.  
  15805. •••Refer to Figure 1.•••
  15806.  
  15807. Figure 1–AppleTalk Protocols and OSI Network Layers
  15808.  
  15809. Figure 2 illustrates the Macintosh AppleTalk Drivers and the layered structure of the
  15810. protocols which are accessible through each driver.  Note that the Routing Table
  15811. Maintenance Protocol isn’t directly accessible to Macintosh Programs.
  15812.  
  15813. •••Refer to Figure 2.•••
  15814.  
  15815. Figure 2–Macintosh AppleTalk Drivers
  15816.  
  15817. The AppleTalk Link Access Protocol (ALAP) provides the lowest-level services of the
  15818. AppleTalk system. Its main function is to control access to the AppleTalk network
  15819. among various competing devices. Each device connected to an AppleTalk network, known
  15820. as a node, is assigned an eight-bit node ID number that identifies the node. ALAP
  15821. ensures that each node on an AppleTalk network has a unique node ID, assigned dynamically
  15822. when the node is started up.
  15823.  
  15824. ALAP provides its clients with node-to-node delivery of data frames on a single
  15825. AppleTalk network. An ALAP frame is a variable-length packet of data preceded and
  15826. followed by control information referred to as the ALAP frame header and frame trailer,
  15827. respectively. The ALAP frame header includes the node IDs of the frame’s destination
  15828. and source nodes. The AppleTalk hardware uses the destination node ID to deliver the
  15829. frame. The frame’s source node ID allows a program in the receiving node to determine
  15830. the identity of the source. A sending node can ask ALAP to send a frame to all nodes
  15831. on the AppleTalk network; this broadcast service is obtained by specifying a destination
  15832. node ID of 255.
  15833.  
  15834. ALAP can have multiple clients in a single node. When a frame arrives at a node, ALAP
  15835. determines which client it should be delivered to by reading the frame’s ALAP protocol
  15836. type. The ALAP protocol type is an eight-bit quantity, contained in the frame’s
  15837. header, that identifies the ALAP client to whom the frame will be sent. ALAP calls
  15838. the client’s protocol handler, which is a software process in the node that reads in
  15839. and then services the frames. The protocol handlers for a node are listed in a protocol
  15840. handler table.
  15841.  
  15842. An ALAP frame trailer contains a 16-bit frame check sequence generated by the AppleTalk
  15843. hardware. The receiving node uses the frame check sequence to detect transmission
  15844. errors, and discards frames with errors. In effect, a frame with an error is “lost”
  15845. in the AppleTalk network, because ALAP doesn’t attempt to recover from errors by
  15846. requesting the sending node to retransmit such frames. Thus ALAP is said to make a
  15847. “best effort” to deliver frames, without any guarantee of delivery.
  15848.  
  15849. An ALAP frame can contain up to 600 bytes of client data. The first two bytes must be
  15850. an integer equal to the length of the client data (including the length bytes themselves).
  15851.  
  15852. Datagram Delivery Protocol (DDP) provides the next-higher level protocol in the
  15853. AppleTalk architecture, managing socket-to-socket delivery of datagrams over AppleTalk
  15854. internets. DDP is an ALAP client, and uses the node-to-node delivery service provided
  15855. by ALAP to send and receive datagrams. Datagrams are packets of data transmitted by
  15856. DDP. A DDP datagram can contain up to 586 bytes of client data. Sockets are logical
  15857. entities within the nodes of a network; each socket within a given node has a unique
  15858. eight-bit socket number.
  15859.  
  15860. On a single AppleTalk network, a socket is uniquely identified by its AppleTalk
  15861. address—its socket number together with its node ID. To identify a socket in the
  15862. scope of an AppleTalk internet, the socket’s AppleTalk address and network number are
  15863. needed. Internets are formed by interconnecting AppleTalk networks via intelligent
  15864. nodes called bridges. A network number is a 16-bit number that uniquely identifies a
  15865. network in an internet. A socket’s AppleTalk address together with its network number
  15866. provide an internet-wide unique socket identifier called an internet address.
  15867.  
  15868. Sockets are owned by socket clients, which typically are software processes in the
  15869. node. Socket clients include code called the socket listener, which receives and
  15870. services datagrams addressed to that socket. Socket clients must open a socket before
  15871. datagrams can be sent or received through it. Each node contains a socket table that
  15872. lists the listener for each open socket.
  15873.  
  15874. A datagram is sent from its source socket through a series of AppleTalk networks,
  15875. being passed on from bridge to bridge, until it reaches its destination network. The
  15876. ALAP in the destination network then delivers the datagram to the node containing the
  15877. destination socket. Within that node the datagram is received by ALAP calling the DDP
  15878. protocol handler, and by the DDP protocol handler in turn calling the destination
  15879. socket listener, which for most applications will be a higher-level protocol such as
  15880. the AppleTalk Transaction Protocol.
  15881.  
  15882. Bridges on AppleTalk internets use the Routing Table Maintenance Protocol (RTMP) to
  15883. maintain routing tables for routing datagrams through the internet. In addition,
  15884. nonbridge nodes use RTMP to determine the number of the network to which they’re
  15885. connected and the node ID of one bridge on their network. The RTMP code in nonbridge
  15886. nodes contains only a subset of RTMP (the RTMP stub), and is a DDP client owning
  15887. socket number 1 (the RTMP socket).
  15888.  
  15889. Socket clients are also known as network-visible entities, because they’re the primary
  15890. accessible entities on an internet. Network-visible entities can choose to identify
  15891. themselves by an entity name, an identifier of the form
  15892.  
  15893.   object:type@zone
  15894.  
  15895. Each of the three fields of this name is an alphanumeric string of up to 32 characters.
  15896. The object and type fields are arbitrary identifiers assigned by a socket client, to
  15897. provide itself with a name and type descriptor (for example, abs:Mailbox). The zone
  15898. field identifies the zone in which the socket client is located; a zone is an arbitrary
  15899. subset of AppleTalk networks in an internet. A socket client can identify itself by
  15900. as many different names as it chooses. These aliases are all treated as independent
  15901. identifiers for the same socket client.
  15902.  
  15903. The Name-Binding Protocol (NBP) maintains a names table in each node that contains
  15904. the name and internet address of each entity in that node. These name-address pairs
  15905. are called NBP tuples. The collection of names tables in an internet is known as the
  15906. names directory.
  15907.  
  15908. NBP allows its clients to add or delete their name-address tuples from the
  15909. node’s names table. It also allows its clients to obtain the internet addresses of
  15910. entities from their names. This latter operation, known as name lookup (in the names
  15911. directory), requires that NBP install itself as a DDP client and broadcast special
  15912. name-lookup packets to the nodes in a specified zone. These datagrams are sent by NBP
  15913. to the names information socket—socket number 2 in every node using NBP.
  15914.  
  15915. NBP clients can use special meta-characters in place of one or more of the three
  15916. fields of the name of an entity it wishes to look up. The character “=” in the object
  15917. or type field signifies “all possible values”. The zone field can be replaced by “*”,
  15918. which signifies “this zone”—the zone in which the NBP client’s node is located. For
  15919. example, an NBP client performing a lookup with the name
  15920.  
  15921.   =:Mailbox@*
  15922.  
  15923. will obtain in return the entity names and internet addresses of all mailboxes in the
  15924. client’s zone (excluding the client’s own names and addresses). The client can specify
  15925. whether one or all of the matching names should be returned.
  15926.  
  15927. NBP clients specify how thorough a name lookup should be by providing NBP with the
  15928. number of times (retry count) that NBP should broadcast the lookup packets and the
  15929. time interval (retry interval) between these retries.
  15930.  
  15931. As noted above, ALAP and DDP provide “best effort” delivery services with no recovery
  15932. mechanism when packets are lost or discarded because of errors. Although for many
  15933. situations such a service suffices, the AppleTalk Transaction Protocol (ATP) provides
  15934. a reliable loss-free transport service. ATP uses transactions, consisting of a transaction
  15935. request and a transaction response, to deliver data reliably. Each transaction is
  15936. assigned a 16-bit transaction ID number to distinguish it from other transactions. A
  15937. transaction request is retransmitted by ATP until a complete response has been received,
  15938. thus allowing for recovery from packet-loss situations. The retry interval and retry
  15939. count are specified by the ATP client sending the request.
  15940.  
  15941. Although transaction requests must be contained in a single datagram, transaction
  15942. responses can consist of as many as eight datagrams. Each datagram in a response is
  15943. assigned a sequence number from 0 to 7, to indicate its ordering within the response.
  15944.  
  15945. ATP is a DDP client, and uses the services provided by DDP to transmit requests and
  15946. responses. ATP supports both at-least-once and exactly-once transactions. Four of the
  15947. bytes in an ATP header, called the user bytes, are provided for use by ATP’s clients—they’re
  15948. ignored by ATP.
  15949.  
  15950. ATP’s transaction model and means of recovering from datagram loss are covered in
  15951. detail below.
  15952.  
  15953. The Echo Protocol (EP) provides an echoing service through static socket number 4
  15954. known as the echoer socket.  The echoer listens for packets received through this
  15955. socket.  Any correctly formed packet sent to the echoer socket on a node will be
  15956. echoed back to its sender.
  15957.  
  15958. This simple protocol can be used for two important purposes:
  15959.  
  15960.   •  EP can be used by any Datagram Delivery Protocol (DDP) client to
  15961.      determine if a particular node (known to have an echoer) is accessible
  15962.      over an internet.
  15963.   •  EP is useful in determining the average time it takes for a packet to
  15964.      travel to a remote node and back.  This is very helpful in developing
  15965.      client-dependent heuristics for estimating the timeouts to be specified
  15966.      by clients of ATP, ASP, and other protocols.
  15967.  
  15968. Programs cannot access EP directly via the AppleTalk Manager.  The EP implementation
  15969. exists solely to respond to EP requests sent by other nodes.  EP is a DDP client
  15970. residing on statically-assigned socket 4, the echoing socket.  Clients wishing to
  15971. send EP requests (and receive EP responses) should use the Datagram Delivery Protocol
  15972. (DDP) to send the appropriate packet.  For more information about the EP packet
  15973. format, see Inside AppleTalk.
  15974.  
  15975. The AppleTalk Session Protocol (ASP) provides for the setting up, maintaining and
  15976. closing down of a session.  A session is a logical relationship between two network
  15977. entities, a workstation and a server.  The workstation tells the server what to do,
  15978. and the server responds with the appropriate actions.  ASP makes sure that the session
  15979. dialog is maintained in the correct sequence and that both ends of the conversation
  15980. are properly participating.
  15981.  
  15982. ASP will generally be used between two communicating network entities where one is
  15983. providing a service to the other (for example, a server is providing a service to a
  15984. workstation) and the service provided is state-dependent.  That is, the response to a
  15985. particular request from an entity is dependent upon other previous requests from that
  15986. entity.  For example, a request to read bytes from a file is dependent upon a previous
  15987. request to open that file in the first place.  However, a request to return the time
  15988. of day is independent of all such previous requests.
  15989.  
  15990. When the service provided is state-dependent, requests must be delivered to the
  15991. server in the same order as generated by the workstation.  ASP guarantees requests
  15992. are delivered to the server in the order in which they are issued, and that duplicate
  15993. requests are never delivered (another requirement of state-dependent service).
  15994.  
  15995. ASP is an asymmetric protocol, providing one set of services to the workstation and a
  15996. different set of services to the server.
  15997.  
  15998. ASP workstation clients initiate (open) sessions, send requests (commands) on that
  15999. session, and close sessions down.  ASP server clients receive and respond
  16000. (through command replies) to these requests.  ASP guarantees that these requests are
  16001. delivered in the same order as they are made, and without duplication.  ASP is also
  16002. responsible for closing down the session if one end fails or becomes unreachable, and
  16003. will inform its client (either server or workstation) of the action.
  16004.  
  16005. ASP also provides various additional services, such as allowing a workstation to
  16006. obtain server status information without opening a session to a server, writing
  16007. blocks of data from the workstation to the server end of the session, and providing
  16008. the ability for a server to send an attention message to the workstation.
  16009.  
  16010. ASP assumes that the workstation client has a mechanism for looking up the network
  16011. address of the server with which it wants to set up a session.
  16012. (Generally this is done using the AppleTalk Name Binding Protocol.)
  16013.  
  16014. Both ends of the session periodically check to see that the other end of the session
  16015. is still responsive.  If one end fails or becomes unreachable the other end closes
  16016. the session.
  16017.  
  16018. ASP is a client of ATP and calls ATP for transport services.
  16019.  
  16020. ASP does not
  16021.  
  16022.   •  ensure that consecutive commands complete in the order in which they
  16023.      were sent (and delivered) to the server
  16024.   •  understand or interpret the syntax or the semantics of the commands
  16025.      sent to the server by the workstation
  16026.   •  allow the server to send commands to the workstation  (The server
  16027.      is allowed to alert the workstation through the server’s attention
  16028.      mechanism only.)
  16029.  
  16030. Note:  The .XPP driver does implement the workstation side of the
  16031.        AppleTalk Filing Protocol login command.
  16032.  
  16033. The AppleTalk Filing Protocol (AFP) allows a workstation on an AppleTalk network to
  16034. access files on an AFP file server.  AFP specifies a remote filing system that provides
  16035. user authentication and an access control mechanism that supports volume and folder-level
  16036. access rights.  For details of AFP, refer to Inside AppleTalk.
  16037.  
  16038. _______________________________________________________________________________
  16039.  
  16040.  
  16041. æKY AppleTalk…Transaction…Protocol
  16042. æC »APPLETALK TRANSACTION PROTOCOL                           AppleTalkManager
  16043. _______________________________________________________________________________
  16044.  
  16045. This section covers ATP in greater depth, providing more detail about three of its
  16046. fundamental concepts:  transactions, buffer allocation, and recovery of lost datagrams.
  16047.  
  16048. _______________________________________________________________________________
  16049.  
  16050. »Transactions
  16051.  
  16052. A transaction is a interaction between two ATP clients, known as the requester and
  16053. the responder. The requester calls the .ATP driver in its node to send a transaction
  16054. request (TReq) to the responder, and then awaits a response. The TReq is received by
  16055. the .ATP driver in the responder’s node and is delivered to the responder. The responder
  16056. then calls its .ATP driver to send back a transaction response (TResp), which is
  16057. received by the requester’s .ATP driver and delivered to the requester. Figure 3
  16058. illustrates this process.
  16059.  
  16060. •••Refer to Figure 3.•••
  16061.  
  16062. Figure 3–Transaction Process
  16063.  
  16064. Simple examples of transactions are:
  16065.  
  16066.   •  read a counter, reset it and send back the value read
  16067.   •  read six sectors of a disk and send back the data read
  16068.   •  write the data sent in the TReq to a printer
  16069.  
  16070. A basic assumption of the transaction model is that the amount of ATP data sent in
  16071. the TReq specifying the operation to be performed is small enough to fit in a single
  16072. datagram. A TResp, on the other hand, may span several datagrams, as in the second
  16073. example. Thus, a TReq is a single datagram, while a TResp consists of up to eight
  16074. datagrams, each of which is assigned a sequence number from 0 to 7 to indicate its
  16075. position in the response.
  16076.  
  16077. The requester must, before calling for a TReq to be sent, set aside enough buffer
  16078. space to receive the datagram(s) of the TResp. The number of buffers allocated (in
  16079. other words, the maximum number of datagrams that the responder can send) is indicated
  16080. in the TReq by an eight-bit bit map. The bits of this bit map are numbered 0 to 7
  16081. (the least significant bit being number 0); each bit corresponds to the response
  16082. datagram with the respective sequence number.
  16083.  
  16084. _______________________________________________________________________________
  16085.  
  16086. »Datagram Loss Recovery
  16087.  
  16088. The way that ATP recovers from datagram loss situations is best explained by an
  16089. example; see Figure 4. Assume that the requester wants to read six sectors of 512
  16090. bytes each from the responder’s disk. The requester puts aside six 512-byte buffers
  16091. (which may or may not be contiguous) for the response datagrams, and calls ATP to
  16092. send a TReq. In this TReq the bit map is set to binary 00111111 or decimal 63. The
  16093. TReq carries a 16-bit transaction ID, generated by the requester’s .ATP driver before
  16094. sending it. (This example assumes that the requester and responder have already
  16095. agreed that each buffer can hold 512
  16096. bytes.) The TReq is delivered to the responder, which reads the six disk sectors and
  16097. sends them back, through ATP, in TResp datagrams bearing sequence numbers 0 through
  16098. 5. Each TResp datagram also carries exactly the same transaction ID as the TReq to
  16099. which they’re responding.
  16100.  
  16101. There are several ways that datagrams may be lost in this case. The original TReq
  16102. could be lost for one of many reasons. The responding node might be too busy to
  16103. receive the TReq or might be out of buffers for receiving it, there could be an
  16104. undetected collision on the network, a bit error in the transmission line, and so on.
  16105. To recover from such errors, the requester’s .ATP driver maintains an ATP retry timer
  16106. for each transaction sent. If this timer expires and the complete TResp has not been
  16107. received, the TReq is retransmitted and the retry timer is restarted.
  16108.  
  16109. A second error situation occurs when one or more of the TResp datagrams isn’t received
  16110. correctly by the requester’s .ATP driver (datagram 1 in Figure 4). Again, the retry
  16111. timer will expire and the complete TResp will not have been received; this will
  16112. result in a retransmission of the TReq. However, to avoid unnecessary retransmission
  16113. of the TResp datagrams already properly received, the bit map of this retransmitted
  16114. TReq is modified to reflect only those datagrams not yet received. Upon receiving
  16115. this TReq, the responder retransmits only the missing response datagrams.
  16116.  
  16117. Another possible failure is that the responder’s .ATP driver goes down or the responder
  16118. becomes unreachable through the underlying network system. In this case, retransmission
  16119. of the TReq could continue indefinitely. To avoid this situation, the requester
  16120. provides a maximum retry count; if this count is exceeded, the requester’s .ATP
  16121. driver returns an appropriate error message to the requester.
  16122.  
  16123. •••Refer to Figure 4.•••
  16124.  
  16125. Figure 4–Datagram Loss Recovery
  16126.  
  16127. Note:  There may be situations where, due to an anticipated delay, you’ll
  16128.        want a request to be retransmitted more than 255 times; specifying a
  16129.        retry count of 255 indicates “infinite retries” to ATP and will cause
  16130.        a message to be retransmitted until the request has either been
  16131.        serviced, or been cancelled through a specific call.
  16132. _______________________________________________________________________________
  16133.  
  16134. »THE APPLETALK MANAGER                                            
  16135. _______________________________________________________________________________
  16136.  
  16137. Finally, in our example, what if the responder is able to provide only four disk
  16138. sectors (having reached the end of the disk) instead of the six requested? To handle
  16139. this situation, there’s an end-of-message (EOM) flag in each TResp datagram. In this
  16140. case, the TResp datagram numbered 3 would come with this flag set. The reception of
  16141. this datagram informs the requester’s .ATP driver that TResps numbered 4 and 5 will
  16142. not be sent and should not be expected.
  16143.  
  16144. When the transaction completes successfully (all expected TResp datagrams are received
  16145. or TResp datagrams numbered 0 to n are received with datagram n’s EOM flag set), the
  16146. requester is informed and can then use the data received in the TResp.
  16147.  
  16148. ATP provides two classes of service:  at-least-once (ALO) and exactly-once (XO). The
  16149. TReq datagram contains an XO flag that’s set if XO service is required and cleared if
  16150. ALO service is adequate. The main difference between the two is in the sequence of
  16151. events that occurs when the TReq is received by the responder’s .ATP driver.
  16152.  
  16153. In the case of ALO service, each time a TReq is received (with the XO flag cleared),
  16154. it’s delivered to the responder by its .ATP driver; this is true even for retransmitted
  16155. TReqs of the same transaction. Each time the TReq is delivered, the responder performs
  16156. the requested operation and sends the necessary TResp datagrams. Thus, the requested
  16157. operation is performed at least once, and perhaps several times, until the transaction
  16158. is completed at the requester’s end.
  16159.  
  16160. The at-least-once service is satisfactory in a variety of situations—for instance, if
  16161. the requester wishes to read a clock or a counter being maintained at the responder’s
  16162. end. However, in other circumstances, repeated execution of the requested operation
  16163. is unacceptable. This is the case, for instance, if the requester is sending data to
  16164. be printed at the responding end; exactly-once service is designed for such situations.
  16165.  
  16166. The responder’s .ATP driver maintains a transactions list of recently received XO
  16167. TReqs. Whenever a TReq is received with its XO flag set, the driver goes through this
  16168. list to see if this is a retransmitted TReq. If it’s the first TReq of a transaction,
  16169. it’s entered into the list and delivered to the responder. The responder executes the
  16170. requested operation and calls its driver to send a TResp. Before sending it out, the
  16171. .ATP driver saves the TResp in the list.
  16172.  
  16173. When a retransmitted TReq for the same XO transaction is received, the responder’s
  16174. .ATP driver will find a corresponding entry in the list. The retransmitted TReq is
  16175. not delivered to the responder; instead, the driver automatically retransmits the
  16176. response datagrams that were saved in the list. In this way, the responder never sees
  16177. the retransmitted TReqs and the requested operation is performed only once.
  16178.  
  16179. ATP must include a mechanism for eventually removing XO entries from the responding
  16180. end’s transaction list; two provisions are made for this. When the requester’s .ATP
  16181. driver has received all the TResp datagrams of a particular transaction, it sends a
  16182. datagram known as a transaction release (TRel); this tells the responder’s .ATP
  16183. driver to remove the transaction from the list. However, the TRel could be lost in
  16184. the network (or the responding end may die, and so on), leaving the entry in the list
  16185. forever. To account for this situation, the responder’s .ATP driver maintains a
  16186. release timer for each transaction. If this timer expires and no activity has occurred
  16187. for the transaction, its entry is removed from the transactions list.
  16188.  
  16189. _______________________________________________________________________________
  16190.  
  16191.  
  16192. æKY About…the…AppleTalk…Manager
  16193. æC »ABOUT THE APPLETALK MANAGER                              AppleTalkManager
  16194. _______________________________________________________________________________
  16195.  
  16196. The AppleTalk Manager is divided into three parts (see Figure 5):
  16197.  
  16198.   •  A lower-level driver called “.MPP” that contains code to implement ALAP,
  16199.      DDP, NBP, and the RTMP stub; this includes separate code resources loaded
  16200.      in when an NBP name is registered or looked up.
  16201.   •  A higher-level driver called “.ATP” that implements ATP.
  16202.   •  A Pascal interface to these two drivers, which is a set of Pascal data
  16203.      types and routines to aid Pascal programmers in calling the AppleTalk
  16204.      Manager.
  16205.  
  16206. •••Refer to Figure 5.•••
  16207.  
  16208. Figure 5–Calling the AppleTalk Manager
  16209.  
  16210. The two drivers and the interface to them are not in ROM; your application must link
  16211. to the appropriate object files.
  16212.  
  16213. Pascal programmers make calls to the AppleTalk Manager’s Pascal interface, which in
  16214. turn makes Device Manager Control calls to the two drivers. Assembly-language programmers
  16215. make Device Manager Control calls directly to the drivers.
  16216.  
  16217. Note:  Pascal programmers can, of course, make PBControl calls directly
  16218.        if they wish.
  16219.  
  16220. The AppleTalk Manager provides ALAP routines that allow a program to:
  16221.  
  16222.   •  send a frame to another node
  16223.   •  receive a frame from another node
  16224.   •  add a protocol handler to the protocol handler table
  16225.   •  remove a protocol handler from the protocol handler table
  16226.  
  16227. Each node may have up to four protocol handlers in its protocol handler table, two of
  16228. which are currently used by DDP.
  16229.  
  16230. By calling DDP, socket clients can:
  16231.  
  16232.   •  send a datagram via a socket
  16233.   •  receive a datagram via a socket
  16234.   •  open a socket and add a socket listener to the socket table
  16235.   •  close a socket and remove a socket listener from the socket table
  16236.  
  16237. Each node may have up to 12 open sockets in its socket table.
  16238.  
  16239. Programs cannot access RTMP directly via the AppleTalk Manager; RTMP exists solely
  16240. for the purpose of providing DDP with routing information.
  16241.  
  16242. The NBP code allows a socket client to:
  16243.  
  16244.   •  register the name and socket number of an entity in the node’s names table
  16245.   •  determine the address (and confirm the existence) of an entity
  16246.   •  delete the name of an entity from the node’s names table
  16247.  
  16248. The AppleTalk Manager’s .ATP driver allows a socket client to do the following:
  16249.  
  16250.   •  open a responding socket to receive requests
  16251.   •  send a request to another socket and get back a response
  16252.   •  receive a request via a responding socket
  16253.   •  send a response via a responding socket
  16254.   •  close a responding socket
  16255.  
  16256. Note:  Although the AppleTalk Manager provides four different protocols
  16257.        for your use, you’re not bound to use all of them. In fact, most
  16258.        programmers will use only the NBP and ATP protocols.
  16259.  
  16260. AppleTalk communicates via channel B of the Serial Communications Controller
  16261. (SCC). When the Macintosh is started up with a disk containing the AppleTalk code,
  16262. the status of serial port B is checked. If port B isn’t being used by another device
  16263. driver, and is available for use by AppleTalk, the .MPP driver is loaded into the
  16264. system heap. On a Macintosh 128K, only the MPP code is loaded at system startup; the
  16265. .ATP driver and NBP code are read into the application heap when the appropriate
  16266. commands are issued. On a Macintosh 512K or XL, all AppleTalk code is loaded into the
  16267. system heap at system startup.
  16268.  
  16269. After loading the AppleTalk code, the .MPP driver installs its own interrupt handlers,
  16270. installs a task into the vertical retrace queue, and prepares the SCC for use. It
  16271. then chooses a node ID for the Macintosh and confirms that the node ID isn’t already
  16272. being used by another node on the network.
  16273.  
  16274. Warning:  For this reason it’s imperative that the Macintosh be connected
  16275.           to the AppleTalk network through serial port B (the printer port)
  16276.           before being switched on.
  16277.  
  16278. The AppleTalk Manager also provides Pascal routines for opening and closing the .MPP
  16279. and .ATP drivers. The open calls allow a program to load AppleTalk code at times
  16280. other than system startup. The close calls allow a program to remove the AppleTalk
  16281. code from the Macintosh; the use of close calls is highly discouraged, since other
  16282. co-resident programs are then “disconnected” from AppleTalk. Both sets of calls are
  16283. described in detail under “Calling the AppleTalk Manager from Pascal”.
  16284.  
  16285. Warning:  If, at system startup, serial port B isn’t available for use by
  16286.           AppleTalk, the .MPP driver won’t open. However, a driver doesn’t
  16287.           return an error message when it fails to open. Pascal programmers
  16288.           must ensure the proper opening of AppleTalk by calling one of the
  16289.           two routines for opening the AppleTalk drivers (either MPPOpen or
  16290.           ATPLoad). If AppleTalk was successfully loaded at system startup,
  16291.           these calls will have no effect; otherwise they’ll check the
  16292.           availability of port B, attempt to load the AppleTalk code, and
  16293.           return an appropriate result code.
  16294.  
  16295. Assembly-language note:  Assembly-language programmers can use the Pascal
  16296.                          routines for opening AppleTalk. They can also check
  16297.                          the availability of port B themselves and then decide
  16298.                          whether to open MPP or ATP. Detailed information on
  16299.                          how to do this is provided in the section “Calling
  16300.                          the AppleTalk Manager from Assembly Language”.
  16301.  
  16302. The two AppleTalk device drivers, named .MPP and .ATP, are included in the 128K ROM.
  16303. The AppleTalk Manager, however (the interface to the drivers), is not in ROM; your
  16304. application must link to the appropriate object files.
  16305.  
  16306. On the Macintosh Plus, you need only open the .MPP driver; this will also load the
  16307. .ATP driver and NBP code automatically. Since, in the 128K ROM, device drivers return
  16308. errors, it’s no longer necessary to check whether port B is free and configured for
  16309. AppleTalk. If port B isn’t available, the .MPP driver won’t open and the result code
  16310. portInUse or portNotCf will be returned.
  16311.  
  16312. Assembly-language note:  When called from assembly language, the Datagram
  16313.                          Delivery Protocol (DDP) allows 14 (instead of 12)
  16314.                          open sockets.
  16315.  
  16316. The changes to the AppleTalk manager increase functionality and resources. Two interfaces
  16317. for the AppleTalk Manager calls are discussed: the new or preferred interface and the
  16318. alternate interface. Picking a node address in the server range, sending packets to
  16319. one’s own node, multiple concurrent NBP requests, sending ATP requests through a
  16320. specified socket and two new ATP calls are also discussed in this section. These
  16321. calls can only be made with the preferred interface.
  16322.  
  16323. _______________________________________________________________________________
  16324.  
  16325.  
  16326. æKY Calling…the…AppleTalk…Manager…from…Pascal
  16327. æC »CALLING THE APPLETALK MANAGER FROM PASCAL                AppleTalkManager
  16328. _______________________________________________________________________________
  16329.  
  16330. This section discusses how to use the AppleTalk Manager from Pascal. Equivalent
  16331. assembly-language information is given in the “Calling the AppleTalk Manager from
  16332. Assembly Language” section.
  16333.  
  16334. You can execute many AppleTalk Manager routines either synchronously (meaning that
  16335. the application can’t continue until the routine is completed) or asynchronously
  16336. (meaning that the application is free to perform other tasks while the routine is
  16337. being executed).
  16338.  
  16339. When an application calls an AppleTalk Manager routine asynchronously, an I/O request
  16340. is placed in the appropriate driver’s I/O queue, and control returns to the calling
  16341. program—possibly even before the actual I/O is completed. Requests are taken from the
  16342. queue one at a time, and processed; meanwhile, the calling program is free to work on
  16343. other things.
  16344.  
  16345. The routines that can be executed asynchronously contain a Boolean parameter called
  16346. async. If async is TRUE, the call is executed asynchronously; otherwise the call is
  16347. executed synchronously. Every time an asynchronous routine call is completed, the
  16348. AppleTalk Manager posts a network event. The message field of the event record will
  16349. contain a handle to the parameter block that was used to make that call.
  16350.  
  16351. Most AppleTalk Manager routines return an integer result code of type OSErr. Each
  16352. routine description lists all of the applicable result codes generated by the AppleTalk
  16353. Manager, along with a short description of what the result code means. Lengthier
  16354. explanations of all the result codes can be found in the summary at the end of the
  16355. chapter. Result codes from other parts of the Operating System may also be returned.
  16356. (See Appendix A for a list of all result codes.)
  16357.  
  16358. Many Pascal calls to the AppleTalk Manager require information passed in a parameter
  16359. block of type ABusRecord. The exact content of an ABusRecord depends on the protocol
  16360. being called:
  16361.  
  16362. TYPE  ABProtoType  =  (lapProto,ddpProto,nbpProto,atpProto);
  16363.       ABusRecord   =  RECORD
  16364.                         abOpcode:        ABCallType; {type of call}
  16365.                         abResult:        INTEGER;    {result code}
  16366.                         abUserReference: LONGINT;    {for your use}
  16367.                         CASE ABProtoType OF
  16368.                           lapProto:
  16369.                             . . .     {ALAP parameters}
  16370.                           ddpProto:
  16371.                             . . .     {DDP parameters}
  16372.                           nbpProto:
  16373.                             . . .     {NBP parameters}
  16374.                           atpProto:
  16375.                             . . .     {ATP parameters}
  16376.                         END;
  16377.                       END;
  16378.  
  16379.       ABRecPtr     = ^ABusRecord;
  16380.       ABRecHandle  = ^ABRecPtr;
  16381.  
  16382. The value of the abOpcode field is inserted by the AppleTalk Manager when the call is
  16383. made, and is always a member of the following set:
  16384.  
  16385. TYPE  ABCallType = (tLAPRead,tLAPWrite,tDDPRead,tDDPWrite,tNBPLookup,
  16386.                     tNBPConfirm,tNBPRegister,tATPSndRequest,
  16387.                     tATPGetRequest,tATPSdRsp,tATPAddRsp,tATPRequest,
  16388.                     tATPRespond);
  16389.  
  16390. The abUserReference field is available for use by the calling program in any way it
  16391. wants. This field isn’t used by the AppleTalk Manager routines or drivers.
  16392.  
  16393. The size of an ABusRecord data structure in bytes is given by one of the following
  16394. constants:
  16395.  
  16396. CONST  lapSize = 20;
  16397.        ddpSize = 26;
  16398.        nbpSize = 26;
  16399.        atpSize = 56;
  16400.  
  16401. Variables of type ABusRecord must be allocated in the heap with Memory Manager NewHandle
  16402. calls. For example:
  16403.  
  16404.   myABRecord := ABRecHandle(NewHandle(ddpSize))
  16405.  
  16406. Warning:  These Memory Manager calls can’t be made inside interrupts.
  16407.  
  16408. Routines that are executed asynchronously return control to the calling program with
  16409. the result code noErr as soon as the call is placed in the driver’s I/O queue. This
  16410. isn’t an indication of successful call completion; it simply indicates that the call
  16411. was successfully queued to the appropriate driver. To determine when the call is
  16412. actually completed, you can either check for a network event or poll the abResult
  16413. field of the call’s ABusRecord. The abResult field, set to 1 when the call is made,
  16414. receives the actual result code upon completion of the call.
  16415.  
  16416. Warning:  A data structure of type ABusRecord is often used by the AppleTalk
  16417.           Manager during an asynchronous call, and so is locked by the
  16418.           AppleTalk Manager. Don’t attempt to unlock or use such a variable.
  16419.  
  16420. Each routine description includes a list of the ABusRecord fields affected by the
  16421. routine. The arrow next to each field name indicates whether it’s an input, output,
  16422. or input/output parameter:
  16423.  
  16424. Arrow    Meaning
  16425.   -->    Parameter is passed to the routine
  16426.   <--    Parameter is returned by the routine
  16427.   <->    Parameter is passed to and returned by the routine
  16428.  
  16429. _______________________________________________________________________________
  16430.  
  16431. »Opening and Closing AppleTalk
  16432.  
  16433. •••Refer to Technical Note #224:•••
  16434.  
  16435. FUNCTION MPPOpen :  OSErr; [Not in ROM]
  16436.  
  16437. MPPOpen first checks whether the .MPP driver has already been loaded; if it has,
  16438. MPPOpen does nothing and returns noErr. If MPP hasn’t been loaded, MPPOpen attempts
  16439. to load it into the system heap. If it succeeds, it then initializes the driver’s
  16440. variables and goes through the process of dynamically assigning a node ID to that
  16441. Macintosh. On a Macintosh 512K or XL, it also loads the .ATP driver and NBP code into
  16442. the system heap.
  16443.  
  16444. If serial port B isn’t configured for AppleTalk, or is already in use, the .MPP
  16445. driver isn’t loaded and an appropriate result code is returned.
  16446.  
  16447. Result codes    noErr        No error
  16448.                 portInUse    Port B is already in use
  16449.                 portNotCf    Port B not configured for AppleTalk
  16450.  
  16451. FUNCTION MPPClose :  OSErr; [Not in ROM]
  16452.  
  16453. MPPClose removes the .MPP driver, and any data structures associated with it, from
  16454. memory. If the .ATP driver or NBP code were also installed, they’re removed as well.
  16455. MPPClose also returns the use of port B to the Serial Driver.
  16456.  
  16457. Warning:  Since other co-resident programs may be using AppleTalk, it’s
  16458.           strongly recommended that you never use this call. MPPClose will
  16459.           completely disable AppleTalk; the only way to restore AppleTalk
  16460.           is to call MPPOpen again.
  16461.  
  16462. _______________________________________________________________________________
  16463.  
  16464. »AppleTalk Link Access Protocol
  16465.  
  16466. »Data Structures
  16467.  
  16468. ALAP calls use the following ABusRecord fields:
  16469.  
  16470. lapProto:
  16471.     (lapAddress:    LAPAdrBlock; {destination or source node ID}
  16472.      lapReqCount:   INTEGER;     {length of frame data or buffer size in bytes}
  16473.      lapActCount:   INTEGER;     {number of frame data bytes actually received}
  16474.      lapDataPtr:    Ptr);        {pointer to frame data or pointer to buffer}
  16475.  
  16476. When an ALAP frame is sent, the lapAddress field indicates the ID of the destination
  16477. node. When an ALAP frame is received, lapAddress returns the ID of the source node.
  16478. The lapAddress field also indicates the ALAP protocol type of the frame:
  16479.  
  16480. TYPE  LAPAdrBlock = PACKED RECORD
  16481.                       dstNodeID:    Byte;  {destination node ID}
  16482.                       srcNodeID:    Byte;  {source node ID}
  16483.                       lapProtType:  ABByte {ALAP protocol type}
  16484.                     END;
  16485.  
  16486. When an ALAP frame is sent, lapReqCount indicates the size of the frame data in bytes
  16487. and lapDataPtr points to a buffer containing the frame data to be sent. When an ALAP
  16488. frame is received, lapDataPtr points to a buffer in which the incoming data can be
  16489. stored and lapReqCount indicates the size of the buffer in bytes. The number of bytes
  16490. actually sent or received is returned in the lapActCount field.
  16491.  
  16492. Each ALAP frame contains an eight-bit ALAP protocol type in the header. ALAP protocol
  16493. types 128 through 255 are reserved for internal use by ALAP, hence the declaration:
  16494.  
  16495. TYPE  ABByte = 1..127; {ALAP protocol type}
  16496.  
  16497. Warning:  Don’t use ALAP protocol type values 1 and 2; they’re reserved
  16498.           for use by DDP. Value 3 through 15 are reserved for internal
  16499.           use by Apple and also shouldn’t be used.
  16500.  
  16501. »Using ALAP
  16502.  
  16503. Most programs will never need to call ALAP, because higher-level protocols will
  16504. automatically call it as necessary. If you do want to send a frame directly via ALAP,
  16505. call the LAPWrite function. If you want to read ALAP frames, you have two choices:
  16506.  
  16507.   •  Call LAPOpenProtocol with NIL for protoPtr (see below); this installs
  16508.      the default protocol handler provided by the AppleTalk Manager. Then
  16509.      call LAPRead to receive frames.
  16510.   •  Write your own protocol handler, and call LAPOpenProtocol to add it
  16511.      to the node’s protocol handler table. The ALAP code will examine every
  16512.      incoming frame and send all those with the correct ALAP protocol type
  16513.      to your protocol handler. See the section “Protocol Handlers and Socket
  16514.      Listeners” for information on how to write a protocol handler.
  16515.  
  16516. When your program no longer wants to receive frames with a particular ALAP protocol
  16517. type value, it can call LAPCloseProtocol to remove the corresponding protocol handler
  16518. from the protocol handler table.
  16519.  
  16520. »ALAP Routines
  16521.  
  16522. FUNCTION LAPOpenProtocol (theLAPType:  ABByte;
  16523.                           protoPtr:  Ptr) :  OSErr; [Not in ROM]
  16524.  
  16525. LAPOpenProtocol adds the ALAP protocol type specified by theLAPType to the
  16526. node’s protocol table. If you provide a pointer to a protocol handler in protoPtr,
  16527. ALAP will send each frame with an ALAP protocol type of theLAPType to that protocol
  16528. handler.
  16529.  
  16530. If protoPtr is NIL, the default protocol handler will be used for receiving frames
  16531. with an ALAP protocol type of theLAPType. In this case, to receive a frame you must
  16532. call LAPRead to provide the default protocol handler with a buffer for placing the
  16533. data. If, however, you’ve written your own protocol handler and protoPtr points to
  16534. it, your protocol handler will have the responsibility for receiving the frame and
  16535. it’s not necessary to call LAPRead.
  16536.  
  16537. Result codes    noErr         No error
  16538.                 lapProtErr    Error attaching protocol type
  16539.  
  16540. FUNCTION LAPCloseProtocol (theLAPType:  ABByte) :  OSErr; [Not in ROM]
  16541.  
  16542. LAPCloseProtocol removes from the node’s protocol table the specified ALAP protocol
  16543. type, as well as its protocol handler.
  16544.  
  16545. Warning:  Don’t close ALAP protocol type values 1 or 2. If you close these
  16546.           protocol types, DDP will be disabled; once disabled, the only way
  16547.           to restore DDP is to restart the system, or to close and then
  16548.           reopen AppleTalk.
  16549.  
  16550. Result codes    noErr         No error
  16551.                 lapProtErr    Error detaching protocol type
  16552.  
  16553. FUNCTION LAPWrite (abRecord:  ABRecHandle;
  16554.                    async:  BOOLEAN) :  OSErr; [Not in ROM]
  16555.  
  16556. ABusRecord
  16557.   <--    abOpcode                {always tLAPWrite}
  16558.   <--    abResult                {result code}
  16559.   -->    abUserReference         {for your use}
  16560.   -->    lapAddress.dstNodeID    {destination node ID}
  16561.   -->    lapAddress.lapProtType  {ALAP protocol type}
  16562.   -->    lapReqCount             {length of frame data}
  16563.   -->    lapDataPtr              {pointer to frame data}
  16564.  
  16565. LAPWrite sends a frame to another node. LAPReqCount and lapDataPtr specify the length
  16566. and location of the data to send. The lapAddress.lapProtType field indicates the ALAP
  16567. protocol type of the frame and the lapAddress.dstNodeID indicates the node ID of the
  16568. node to which the frame should be sent.
  16569.  
  16570. Note:  The first two bytes of an ALAP frame’s data must contain the length
  16571.        in bytes of that data, including the length bytes themselves.
  16572.  
  16573. Result codes    noErr            No error
  16574.                 excessCollsns    Unable to contact destination node;
  16575.                                  packet not sent
  16576.                 ddpLenErr        ALAP data length too big
  16577.                 lapProtErr       Invalid ALAP protocol type
  16578.  
  16579. FUNCTION LAPRead (abRecord:  ABRecHandle;
  16580.                   async:  BOOLEAN) :  OSErr; [Not in ROM]
  16581.  
  16582. ABusRecord
  16583.   <--    abOpcode                {always tLAPRead}
  16584.   <--    abResult                {result code}
  16585.   -->    abUserReference         {for your use}
  16586.   <--    lapAddress.dstNodeID    {destination node ID}
  16587.   <--    lapAddress.srcNodeID    {source node ID}
  16588.   -->    lapAddress.lapProtType  {ALAP protocol type}
  16589.   -->    lapReqCount             {buffer size in bytes}
  16590.   <--    lapActCount             {number of frame data bytes actually received}
  16591.   -->    lapDataPtr              {pointer to buffer}
  16592.  
  16593. LAPRead receives a frame from another node. LAPReqCount and lapDataPtr specify the
  16594. size and location of the buffer that will receive the frame data. If the buffer isn’t
  16595. large enough to hold all of the incoming frame data, the extra bytes will be discarded
  16596. and buf2SmallErr will be returned. The number of bytes actually received is returned
  16597. in lapActCount. Only frames with ALAP protocol type equal to lapAddress.lapProtType
  16598. will be received. The node IDs of the frame’s source and destination nodes are returned
  16599. in lapAddress.srcNodeID and lapAddress.dstNodeID. You can determine whether the
  16600. packet was broadcast to you by examining the value of lapAddress.dstNodeID—if the
  16601. packet was broadcast it’s equal to 255, otherwise it’s equal to your node ID.
  16602.  
  16603. Note:  You should issue LAPRead calls only for ALAP protocol types that were
  16604.        opened (via LAPOpenProtocol) to use the default protocol handler.
  16605.  
  16606. Warning:  If you close a protocol type for which there are still LAPRead
  16607.           calls pending, the calls will be canceled but the memory occupied
  16608.           by their ABusRecords will not be released. For this reason, before
  16609.           closing a protocol type, call LAPRdCancel to cancel any pending
  16610.           LAPRead calls associated with that protocol type.
  16611.  
  16612. Result codes    noErr           No error
  16613.                 buf2SmallErr    Frame too large for buffer
  16614.                 readQErr        Invalid protocol type or protocol type not
  16615.                                 found in table
  16616.  
  16617. FUNCTION LAPRdCancel (abRecord:  ABRecHandle) :  OSErr; [Not in ROM]
  16618.  
  16619. Given the handle to the ABusRecord of a previously made LAPRead call, LAPRdCancel
  16620. dequeues the LAPRead call, provided that a packet satisfying the LAPRead has not
  16621. already arrived. LAPRdCancel returns noErr if the LAPRead call is successfully removed
  16622. from the queue. If LAPRdCancel returns recNotFnd, check the abResult field to verify
  16623. that the LAPRead has been completed and determine its outcome.
  16624.  
  16625. Result codes    noErr        No error
  16626.                 readQErr     Invalid protocol type or protocol type not
  16627.                              found in table
  16628.                 recNotFnd    ABRecord not found in queue
  16629.  
  16630. »Example
  16631.  
  16632. This example sends an ALAP packet synchronously and waits asynchronously for a response.
  16633. Assume that both nodes are using a known protocol type (in this case, 73) to receive
  16634. packets, and that the destination node has a node ID of 4.
  16635.  
  16636. VAR
  16637.   myABRecord: ABRecHandle;
  16638.   myBuffer: PACKED ARRAY [0..599] OF CHAR; {buffer for both send and receive}
  16639.   myLAPType: Byte;
  16640.   errCode, index, dataLen: INTEGER;
  16641.   someText: Str255;
  16642.   async: BOOLEAN;
  16643.  
  16644. BEGIN
  16645.   errCode := MPPOpen;
  16646.   IF errCode <> noErr THEN
  16647.     WRITELN('Error in opening AppleTalk')
  16648.     {Maybe serial port B isn't available for use by AppleTalk}
  16649.   ELSE
  16650.     BEGIN
  16651.     {Call Memory Manager to allocate ABusRecord}
  16652.     myABRecord := ABRecHandle(NewHandle(lapSize));
  16653.     myLAPType := 73;
  16654.    {Enter myLAPType into protocol handler table and install default handler to }
  16655.     { service frames of that ALAP type. No packets of that ALAP type will be }
  16656.     { received until we call LAPRead.}
  16657.     errCode := LAPOpenProtocol(myLAPType, NIL);
  16658.     IF errCode <> noErr THEN
  16659.       WRITELN('Error while opening the protocol type')
  16660.       {Have we opened too many protocol types? Remember that DDP uses two of }
  16661.       { them.}
  16662.     ELSE
  16663.       BEGIN
  16664.       {Prepare data to be sent}
  16665.       someText := 'This data will be in the ALAP data area';
  16666.       {The .MPP implementation requires that the first two bytes of the ALAP }
  16667.       { data field contain the length of the data, including the length bytes }
  16668.       { themselves.}
  16669.       dataLen := LENGTH(someText) + 2;
  16670.       buffer[0] := CHR(dataLen DIV 256); {high byte of data length}
  16671.       buffer[1] := CHR(dataLen MOD 256); {low byte of data length}
  16672.       FOR index := 1 TO dataLen - 2 DO {stuff buffer with packet data}
  16673.         buffer[index + 1] := someText[index];
  16674.       async := FALSE;
  16675.       WITH myABRecord^^ DO {fill parameters in the ABusRecord}
  16676.         BEGIN
  16677.         lapAddress.lapProtType := myLAPType;
  16678.         lapAddress.dstNodeID := 4;
  16679.         lapReqCount := dataLen;
  16680.         lapDataPtr := @buffer;
  16681.         END;
  16682.       {Send the frame}
  16683.       errCode := LAPWrite(myABRecord, async);
  16684.       {In the case of a sync call, errCode and the abResult field of }
  16685.       { the myABRecord will contain the same result code. We can also }
  16686.       { reuse myABRecord, since we know whether the call has completed.}
  16687.       IF errCode <> noErr THEN
  16688.         WRITELN('Error while writing out the packet')
  16689.         {Maybe the receiving node wasn't on-line}
  16690.       ELSE
  16691.         BEGIN
  16692.         {We have sent out the packet and are now waiting for a response. We }
  16693.         { issue an async LAPRead call so that we don't “hang” waiting for a }
  16694.         { response that may not come.}
  16695.         async := TRUE;
  16696.         WITH myABRecord^^ DO
  16697.           BEGIN
  16698.           lapAddress.lapProtType := myLAPType;
  16699.           {ALAP type we want to receive }
  16700.           lapReqCount := 600; {our buffer is maximum size}
  16701.           lapDataPtr := @buffer;
  16702.           END;
  16703.         errCode := LAPRead(myABRecord, async); {wait for a packet}
  16704.         IF errCode <> noErr THEN
  16705.           WRITELN('Error while trying to queue up a LAPRead')
  16706.           {Was the protocol handler installed correctly?}
  16707.         ELSE
  16708.           BEGIN
  16709.           {We can either sit here in a loop and poll the abResult }
  16710.           { field or just exit our code and use the event }
  16711.           { mechanism to flag us when the packet arrives.}
  16712.           CheckForMyEvent; {your procedure for checking for a network event}
  16713.           errCode := LAPCloseProtocol(myLAPType);
  16714.           IF errCode <> noErr THEN
  16715.             WRITELN('Error while closing the protocol type');
  16716.           END;
  16717.         END;
  16718.       END;
  16719.     END;
  16720. END.
  16721.  
  16722.  
  16723. _______________________________________________________________________________
  16724.  
  16725. »Datagram Delivery Protocol
  16726.  
  16727. »Data Structures
  16728.  
  16729. DDP calls use the following ABusRecord fields:
  16730.  
  16731. ddpProto:
  16732.     (ddpType:      Byte;       {DDP protocol type}
  16733.      ddpSocket:    Byte;       {source or listening socket number}
  16734.      ddpAddress:   AddrBlock;  {destination or source socket address}
  16735.      ddpReqCount:  INTEGER;    {length of datagram data or buffer size in bytes}
  16736.      ddpActCount:  INTEGER;    {number of bytes actually received}
  16737.      ddpDataPtr:   Ptr;        {pointer to buffer}
  16738.      ddpNodeID:    Byte);      {original destination node ID}
  16739.  
  16740. When a DDP datagram is sent, ddpReqCount indicates the size of the datagram data in
  16741. bytes and ddpDataPtr points to a buffer containing the datagram data. DDPSocket
  16742. specifies the socket from which the datagram should be sent. DDPAddress is the internet
  16743. address of the socket to which the datagram should be sent:
  16744.  
  16745. TYPE  AddrBlock = PACKED RECORD
  16746.                     aNet:     INTEGER;  {network number}
  16747.                     aNode:    Byte;     {node ID}
  16748.                     aSocket:  Byte      {socket number}
  16749.                   END;
  16750.  
  16751. Note:  The network number you specify in ddpAddress.aNet tells MPP whether
  16752.        to create a long header (for an internet) or a short header (for a
  16753.        local network only). A short DDP header will be sent if ddpAddress.aNet
  16754.        is 0 or equal to the network number of the local network.
  16755.  
  16756. When a DDP datagram is received, ddpDataPtr points to a buffer in which the incoming
  16757. data can be stored and ddpReqCount indicates the size of the buffer in bytes. The
  16758. number of bytes actually sent or received is returned in the ddpActCount field.
  16759. DDPAddress is the internet address of the socket from which the datagram was sent.
  16760.  
  16761. DDPType is the DDP protocol type of the datagram, and ddpSocket specifies the socket
  16762. that will receive the datagram.
  16763.  
  16764. Warning:  DDP protocol types 1 through 15 and DDP socket numbers 1 through 63
  16765.           are reserved by Apple for internal use. Socket numbers 64 through 127
  16766.           are available for experimental use. Use of these experimental sockets
  16767.           isn’t recommended for commercial products, since there’s no mechanism
  16768.           for eliminating conflicting usage by different developers.
  16769.  
  16770. »Using DDP
  16771.  
  16772. Before it can use a socket, the program must call DDPOpenSocket, which adds a socket
  16773. and its socket listener to the socket table. When a program is finished using a
  16774. socket, call DDPCloseSocket, which removes the socket’s entry from the socket table.
  16775. To send a datagram via DDP, call DDPWrite. To receive datagrams, you have two choices:
  16776.  
  16777.   •  Call DDPOpenSocket with NIL for sktListener (see below); this installs
  16778.      the default socket listener provided by the AppleTalk Manager. Then call
  16779.      DDPRead to receive datagrams.
  16780.   •  Write your own socket listener and call DDPOpenSocket to install it. DDP
  16781.      will call your socket listener for every incoming datagram for that
  16782.      socket; in this case, you shouldn’t call DDPRead. For information on how
  16783.      to write a socket listener, see the section “Protocol Handlers and Socket
  16784.      Listeners”.
  16785.  
  16786. To cancel a previously issued DDPRead call (provided it’s still in the queue), call
  16787. DDPRdCancel.
  16788.  
  16789. »DDP Routines
  16790.  
  16791. FUNCTION DDPOpenSocket (VAR theSocket:  Byte;
  16792.                         sktListener:  Ptr) :  OSErr; [Not in ROM]
  16793.  
  16794. DDPOpenSocket adds a socket and its socket listener to the socket table. If theSocket
  16795. is nonzero, it must be in the range 64 to 127, and it specifies the socket’s number;
  16796. if theSocket is 0, DDPOpenSocket dynamically assigns a socket number in the range 128
  16797. to 254, and returns it in theSocket. SktListener contains a pointer to the socket
  16798. listener; if it’s NIL, the default listener will be used.
  16799.  
  16800. If you’re using the default socket listener, you must then call DDPRead to receive a
  16801. datagram (in order to specify buffer space for the default socket listener). If,
  16802. however, you’ve written your own socket listener and sktListener points to it, your
  16803. listener will provide buffers for receiving datagrams and you shouldn’t use DDPRead
  16804. calls.
  16805.  
  16806. DDPOpenSocket will return ddpSktErr if you pass the number of an already opened
  16807. socket, if you pass a socket number greater than 127, or if the socket table is
  16808. full.
  16809.  
  16810. Note:  The range of static socket numbers 1 through 63 is reserved by Apple
  16811.        for internal use. Socket numbers 64 through 127 are available for
  16812.        unrestricted experimental use.
  16813.  
  16814. Result codes    noErr        No error
  16815.                 ddpSktErr    Socket error
  16816.  
  16817. FUNCTION DDPCloseSocket (theSocket:  Byte) :  OSErr; [Not in ROM]
  16818.  
  16819. DDPCloseSocket removes the entry of the specified socket from the socket table and
  16820. cancels all pending DDPRead calls that have been made for that socket. If you pass a
  16821. socket number of 0, or if you attempt to close a socket that isn’t open, DDPCloseSocket
  16822. will return ddpSktErr.
  16823.  
  16824. Result codes    noErr        No error
  16825.                 ddpSktErr    Socket error
  16826.  
  16827. FUNCTION DDPWrite (abRecord:  ABRecHandle; doChecksum:  BOOLEAN;
  16828.                    async:  BOOLEAN) :  OSErr; [Not in ROM]
  16829.  
  16830. ABusRecord
  16831.   <--    abOpcode         {always tDDPWrite}
  16832.   <--    abResult         {result code}
  16833.   -->    abUserReference  {for your use}
  16834.   -->    ddpType          {DDP protocol type}
  16835.   -->    ddpSocket        {source socket number}
  16836.   -->    ddpAddress       {destination socket address}
  16837.   -->    ddpReqCount      {length of datagram data}
  16838.   -->    ddpDataPtr       {pointer to buffer}
  16839.  
  16840. DDPWrite sends a datagram to another socket. DDPReqCount and ddpDataPtr specify the
  16841. length and location of the data to send. The ddpType field indicates the DDP protocol
  16842. type of the frame, and ddpAddress is the complete internet address of the socket to
  16843. which the datagram should be sent. DDPSocket specifies the socket from which the
  16844. datagram should be sent. Datagrams sent over the internet to a node on an AppleTalk
  16845. network different from the sending node’s network have an optional software checksum
  16846. to detect errors that might occur inside the intermediate bridges. If doChecksum is
  16847. TRUE, DDPWrite will compute this checksum; if it’s FALSE, this software checksum
  16848. feature is ignored.
  16849.  
  16850. Note:  The destination socket can’t be in the same node as the program
  16851.        making the DDPWrite call.
  16852.  
  16853. Result codes    noErr          No error
  16854.                 ddpLenErr      Datagram length too big
  16855.                 ddpSktErr      Source socket not open
  16856.                 noBridgeErr    No bridge found
  16857.  
  16858. FUNCTION DDPRead (abRecord:  ABRecHandle; retCksumErrs:  BOOLEAN;
  16859.                   async:  BOOLEAN) :  OSErr; [Not in ROM]
  16860.  
  16861. ABusRecord
  16862.   <--    abOpcode         {always tDDPRead}
  16863.   <--    abResult         {result code}
  16864.   -->    abUserReference  {for your use}
  16865.   <--    ddpType          {DDP protocol type}
  16866.   -->    ddpSocket        {listening socket number}
  16867.   <--    ddpAddress       {source socket address}
  16868.   -->    ddpReqCount      {buffer size in bytes}
  16869.   <--    ddpActCount      {number of bytes actually received}
  16870.   -->    ddpDataPtr       {pointer to buffer}
  16871.   <--    ddpNodeID        {original destination node ID}
  16872.  
  16873. DDPRead receives a datagram from another socket. The size and location of the buffer
  16874. that will receive the data are specified by ddpReqCount and ddpDataPtr. If the buffer
  16875. isn’t large enough to hold all of the incoming frame data, the extra bytes will be
  16876. discarded and buf2SmallErr will be returned. The number of bytes actually received is
  16877. returned in ddpActCount. DDPSocket specifies the socket to receive the datagram (the
  16878. “listening” socket). The node to which the packet was sent is returned in ddpNodeID;
  16879. if the packet was broadcast ddpNodeID will contain 255. The address of the socket
  16880. that sent the packet is returned in ddpAddress. If retCksumErrs is FALSE, DDPRead
  16881. will discard any packets received with an invalid checksum and inform the caller of
  16882. the error. If retCksumErrs is TRUE, DDPRead will deliver all packets, whether or not
  16883. the checksum is valid; it will also notify the caller when there’s a checksum error.
  16884.  
  16885. Note:  The sender of the datagram must be in a different node from the
  16886.        receiver. You should issue DDPRead calls only for receiving datagrams
  16887.        for sockets opened with the default socket listener; see the
  16888.        description of DDPOpenSocket.
  16889.  
  16890. Note:  If the buffer provided isn’t large enough to hold all of the incoming
  16891.        frame data (buf2SmallErr), the checksum can’t be calculated; in this
  16892.        case, DDPRead will deliver packets even if retCksumErrs is FALSE.
  16893.  
  16894. Result codes    noErr           No error
  16895.                 buf2SmallErr    Datagram too large for buffer
  16896.                 cksumErr        Checksum error
  16897.                 ddpLenErr       Datagram length too big
  16898.                 ddpSktErr       Socket error
  16899.                 readQErr        Invalid socket or socket not found in table
  16900.  
  16901. FUNCTION DDPRdCancel (abRecord:  ABRecHandle) :  OSErr; [Not in ROM]
  16902.  
  16903. Given the handle to the ABusRecord of a previously made DDPRead call, DDPRdCancel
  16904. dequeues the DDPRead call, provided that a packet satisfying the DDPRead hasn’t
  16905. already arrived. DDPRdCancel returns noErr if the DDPRead call is successfully removed
  16906. from the queue. If DDPRdCancel returns recNotFnd, check the abResult field of abRecord
  16907. to verify that the DDPRead has been completed and determine its outcome.
  16908.  
  16909. Result codes    noErr        No error
  16910.                 readQErr     Invalid socket or socket not found in table
  16911.                 recNotFnd    ABRecord not found in queue
  16912.  
  16913. »Example
  16914.  
  16915. This example sends a DDP packet synchronously and waits asynchronously for a response.
  16916. Assume that both nodes are using a known socket number (in this case, 30) to receive
  16917. packets. Normally, you would want to use NBP to look up your destination’s socket
  16918. address.
  16919.  
  16920. VAR
  16921.   myABRecord: ABRecHandle;
  16922.   myBuffer: PACKED ARRAY [0..599] OF CHAR; {buffer for both send and receive}
  16923.   mySocket: Byte;
  16924.   errCode, index, dataLen: INTEGER;
  16925.   someText: Str255;
  16926.   async, retCksumErrs, doChecksum: BOOLEAN;
  16927.  
  16928. BEGIN
  16929.   errCode := MPPOpen;
  16930.   IF errCode <> noErr THEN
  16931.     WRITELN('Error in opening AppleTalk')
  16932.     {Maybe serial port B isn't available for use by AppleTalk}
  16933.   ELSE
  16934.     BEGIN
  16935.       {Call Memory Manager to allocate ABusRecord}
  16936.       myABRecord := ABRecHandle(NewHandle(ddpSize));
  16937.       mySocket := 30;
  16938.   {Add mySocket to socket table and install default socket listener to service }
  16939. { datagrams addressed to that socket. No packets addressed to mySocket will be }
  16940.       { received until we call DDPRead. }
  16941.       errCode := DDPOpenSocket(mySocket, NIL);
  16942.       IF errCode <> noErr THEN
  16943.         WRITELN('Error while opening the socket')
  16944.       {Have we opened too many socket listeners? Remember that DDP uses two of }
  16945.         { them.}
  16946.       ELSE
  16947.         BEGIN
  16948.           {Prepare data to be sent}
  16949.           someText := 'This is a sample datagram';
  16950.           dataLen := LENGTH(someText);
  16951.           FOR index := 0 TO dataLen - 1 DO {stuff buffer with packet data}
  16952.             myBuffer[index] := someText[index + 1];
  16953.           async := FALSE;
  16954.           WITH myABRecord^^ DO {fill the parameters in the ABusRecord}
  16955.             BEGIN
  16956.               ddpType := 5;
  16957.               ddpAddress.aNet := 0; {send on “our” network}
  16958.               ddpAddress.aNode := 34;
  16959.               ddpAddress.aSocket := mySocket;
  16960.               ddpReqCount := dataLen;
  16961.               ddpDataPtr := @myBuffer;
  16962.             END;
  16963.           doChecksum := FALSE;
  16964.     {If packet contains a DDP long header, compute checksum and insert it into }
  16965.           { the header.}
  16966.           errCode := DDPWrite(myABRecord, doChecksum, async); {send packet}
  16967.      {In the case of a sync call, errCode and the abResult field of myABRecord }
  16968.    { will contain the same result code. We can also reuse myABRecord, since we }
  16969.           { know whether the call has completed.}
  16970.           IF errCode <> noErr THEN
  16971.             WRITELN('Error while writing out the packet')
  16972.             {Maybe the receiving node wasn't on-line}
  16973.           ELSE
  16974.             BEGIN
  16975.            {We have sent out the packet and are now waiting for a response. We }
  16976.            { issue an async DDPRead call so that we don't “hang” waiting for a }
  16977.           { response that may not come. To cancel the async read call, we must }
  16978.               { close the socket associated with the call or call DDPRdCancel.}
  16979.               async := TRUE;
  16980.               retCksumErrs := TRUE; {return packets even if }
  16981.                                     { they have a checksum error}
  16982.               WITH myABRecord^^ DO
  16983.                 BEGIN
  16984.                   ddpSocket := mySocket;
  16985.                   ddpReqCount := 600; {our reception buffer is max size}
  16986.                   ddpDataPtr := @myBuffer;
  16987.                 END;
  16988.               {Wait for a packet asynchronously}
  16989.               errCode := DDPRead(myABRecord, retCksumErrs, async);
  16990.               IF errCode <> noErr THEN
  16991.                 WRITELN('Error while trying to queue up a DDPRead')
  16992.                 {Was the socket listener installed correctly?}
  16993.               ELSE
  16994.                 BEGIN
  16995.                   {We can either sit here in a loop and poll the }
  16996.                   { abResult field or just exit our code and use the }
  16997.                   { event mechanism to flag us when the packet arrives.}
  16998.                   CheckForMyEvent; {your procedure for checking for a }
  16999.                                    { network event}
  17000.                   {If there were no errors, a packet is inside the array }
  17001.                   { mybuffer, the length is in ddpActCount, and the }
  17002.                   { address of the sending socket is in ddpAddress. }
  17003.                   { Process the packet received here and report any errors.}
  17004.                   errCode := DDPCloseSocket(mySocket); {we're done with it}
  17005.                   IF errCode <> noErr THEN
  17006.                     WRITELN('Error while closing the socket');
  17007.                 END;
  17008.             END;
  17009.         END;
  17010.     END;
  17011. END.
  17012.  
  17013. _______________________________________________________________________________
  17014.  
  17015. »AppleTalk Transaction Protocol
  17016.  
  17017. »Data Structures
  17018.  
  17019. ATP calls use the following ABusRecord fields:
  17020.  
  17021. atpProto:
  17022.   (atpSocket:     Byte;        {listening or responding socket number}
  17023.    atpAddress:    AddrBlock;   {destination or source socket address}
  17024.    atpReqCount:   INTEGER;     {request size or buffer size}
  17025.    atpDataPtr:    Ptr;         {pointer to buffer}
  17026.    atpRspBDSPtr:  BDSPtr;      {pointer to response BDS}
  17027.    atpBitMap:     BitMapType;  {transaction bit map}
  17028.    atpTransID:    INTEGER;     {transaction ID}
  17029.    atpActCount:   INTEGER;     {number of bytes actually received}
  17030.    atpUserData:   LONGINT;     {user bytes}
  17031.    atpXO:         BOOLEAN;     {exactly-once flag}
  17032.    atpEOM:        BOOLEAN;     {end-of-message flag}
  17033.    atpTimeOut:    Byte;        {retry timeout interval in seconds}
  17034.    atpRetries:    Byte;        {maximum number of retries}
  17035.    atpNumBufs:    Byte;        {number of elements in response BDS or number }
  17036.                                { of response packets sent}
  17037.    atpNumRsp:     Byte;        {number of response packets received or }
  17038.                                { sequence number}
  17039.    atpBDSSize:    Byte;        {number of elements in response BDS}
  17040.    atpRspUData:   LONGINT;     {user bytes sent or received in transaction }
  17041.                                { response}
  17042.    atpRspBuf:     Ptr;         {pointer to response message buffer}
  17043.    atpRspSize:    INTEGER);    {size of response message buffer}
  17044.   
  17045. The socket receiving the request or sending the response is identified by atpSocket.
  17046. ATPAddress is the address of either the destination or the source socket of a transaction,
  17047. depending on whether the call is sending or receiving data, respectively. ATPDataPtr
  17048. and atpReqCount specify the location and size
  17049. (in bytes) of a buffer that either contains a request or will receive a request. The
  17050. number of bytes actually received in a request is returned in atpActCount. ATPTransID
  17051. specifies the transaction ID. The transaction bit map is contained in atpBitMap, in
  17052. the form:
  17053.  
  17054. TYPE BitMapType = PACKED ARRAY[0..7] OF BOOLEAN;
  17055.  
  17056. Each bit in the bit map corresponds to one of the eight possible packets in a response.
  17057. For example, when a request is made for which five response packets are expected, the
  17058. bit map sent is binary 00011111 or decimal 31. If the second packet in the response
  17059. is lost, the requesting socket will retransmit the request with a bit map of binary
  17060. 00000010 or decimal 2.
  17061.  
  17062. ATPUserData contains the user bytes of an ATP header. ATPXO is TRUE if the transaction
  17063. is to be made with exactly-once service. ATPEOM is TRUE if the response packet is the
  17064. last packet of a transaction. If the number of responses is less than the number that
  17065. were requested, then ATPEOM must also be TRUE. ATPNumRsp contains either the number
  17066. of responses received or the sequence number of a response.
  17067.  
  17068. The timeout interval in seconds and the maximum number of times that a request should
  17069. be made are indicated by atpTimeOut and atpRetries, respectively.
  17070.  
  17071. Note:  Setting atpRetries to 255 will cause the request to be retransmitted
  17072.        indefinitely, until a full response is received or the call is canceled.
  17073.  
  17074. ATP provides a data structure, known as a response buffer data structure
  17075. (response BDS), for allocating buffer space to receive the datagram(s) of the response.
  17076. A response BDS is an array of one to eight elements. Each BDS element defines the
  17077. size and location of a buffer for receiving one response datagram; they’re numbered 0
  17078. to 7 to correspond to the sequence numbers of the response datagrams.
  17079.  
  17080. ATP needs a separate buffer for each response datagram expected, since packets may
  17081. not arrive in the proper sequence. It does not, however, require you to set up and
  17082. use the BDS data structure to describe the response buffers; if you
  17083. don’t, ATP will do it for you. Two sets of calls are provided for both requests and
  17084. responses; one set requires you to allocate a response BDS and the other doesn’t.
  17085.  
  17086. Assembly-language note:  The two calls that don’t require you to define a BDS
  17087.                          data structure (ATPRequest and ATPResponse) are
  17088.                          available in Pascal only.
  17089.  
  17090. The number of BDS elements allocated (in other words, the maximum number of datagrams
  17091. that the responder can send) is indicated in the TReq by an eight-bit bit map. The
  17092. bits of this bit map are numbered 0 to 7 (the least significant bit being number 0);
  17093. each bit corresponds to the response datagram with the respective sequence number.
  17094.  
  17095. ATPRspBDSPtr and atpBDSSize indicate the location and number of elements in the
  17096. response BDS, which has the following structure:
  17097.  
  17098. TYPE  BDSElement =
  17099.              RECORD
  17100.                buffSize:   INTEGER;  {buffer size in bytes}
  17101.                buffPtr:    Ptr;      {pointer to buffer}
  17102.                dataSize:   INTEGER;  {number of bytes actually received}
  17103.                userBytes:  LONGINT   {user bytes}
  17104.              END;
  17105.  
  17106.       BDSType = ARRAY[0..7] OF BDSElement; {response BDS}
  17107.       BDSPtr  = ^BDSType;
  17108.  
  17109. ATPNumBufs indicates the number of elements in the response BDS that contain information.
  17110. In most cases, you can allocate space for your variables of BDSType statically with a
  17111. VAR declaration. However, you can allocate only the minimum space required by your
  17112. ATP calls by doing the following:
  17113.  
  17114.   VAR myBDSPtr:  BDSPtr;
  17115.       . . .
  17116.   numOfBDS := 3; {number of elements needed}
  17117.   myBDSPtr := BDSPtr(NewPtr(SIZEOF(BDSElement) * numOfBDS));
  17118.  
  17119. Note:  The userBytes field of the BDSElement and the atpUserData field
  17120.        of the ABusRecord represent the same information in the datagram.
  17121.        Depending on the ATP call made, one or both of these fields will be used.
  17122.  
  17123. »Using ATP
  17124.  
  17125. Before you can use ATP on a Macintosh 128K, the .ATP driver must be read from the
  17126. system resource file via an ATPLoad call. The .ATP driver loads itself into the
  17127. application heap and installs a task into the vertical retrace queue.
  17128.  
  17129. Warning:  When another application starts up, the application heap is
  17130.           reinitialized; on a Macintosh 128K, this means that the ATP
  17131.           code is lost (and must be reloaded by the next application).
  17132.  
  17133. When you’re through using ATP on a Macintosh 128K, call ATPUnload—the system will be
  17134. returned to the state it was in before the .ATP driver was opened.
  17135.  
  17136. On a Macintosh 512K or XL, the .ATP driver will have been loaded into the system heap
  17137. either at system startup or upon execution of MPPOpen or ATPLoad. ATPUnload has no
  17138. effect on a Macintosh 512K or XL.
  17139.  
  17140. To send a transaction request, call ATPSndRequest or ATPRequest. The .ATP driver will
  17141. automatically select and open a socket through which the request datagram will be
  17142. sent, and through which the response datagrams will be received. The requester must
  17143. specify the full network address (network number, node ID, and socket number) of the
  17144. socket to which the request is to be sent. This socket is known as the responding
  17145. socket, and its address must be known in advance by the requester.
  17146.  
  17147. At the responder’s end, before a transaction request can be received, a responding
  17148. socket must be opened, and the appropriate calls be made, to receive a request. To do
  17149. this, the responder first makes an ATPOpenSocket call which allows the responder to
  17150. specify the address (or part of it) of the requesters from whom it’s willing to
  17151. accept transaction requests. Then it issues an ATPGetRequest call to provide ATP with
  17152. a buffer for receiving a request; when a request is received, ATPGetRequest is completed.
  17153. The responder can queue up several ATPGetRequest calls, each of which will be completed
  17154. as requests are received.
  17155.  
  17156. Upon receiving a request, the responder performs the requested operation, and then
  17157. prepares the information to be returned to the requester. It then calls ATPSndRsp (or
  17158. ATPResponse) to send the response. Actually, the responder can issue the ATPSndRsp
  17159. call with only part (or none) of the response specified. Additional portions of the
  17160. response can be sent later by calling ATPAddRsp.
  17161.  
  17162. The ATPSndRsp and ATPAddRsp calls provide flexibility in the design (and range of
  17163. types) of transaction responders. For instance, the responder may, for some reason,
  17164. be forced to send the responses out of sequence. Also, there might be memory constraints
  17165. that force sending the complete transaction response in parts. Even though eight
  17166. response datagrams might need to be sent, the responder might have only enough memory
  17167. to build one datagram at a time. In this case, it would build the first response
  17168. datagram and call ATPSndRsp to send it. It would then build the second response
  17169. datagram in the same buffer and call ATPAddRsp to send it; and so on, for the third
  17170. through eighth response datagrams.
  17171.  
  17172. A responder can close a responding socket by calling ATPCloseSocket. This call cancels
  17173. all pending ATP calls for that socket, such as ATPGetRequest, ATPSndRsp, and ATPResponse.
  17174.  
  17175. For exactly-once transactions, the ATPSndRsp and ATPAddRsp calls don’t terminate
  17176. until the entire transaction has completed (that is, the responding end receives a
  17177. release packet, or the release timer has expired).
  17178.  
  17179. To cancel a pending, asynchronous ATPSndRequest or ATPRequest call, call ATPReqCancel.
  17180. To cancel a pending, asynchronous ATPSndRsp or ATPResponse call, call ATPRspCancel.
  17181. Pending asynchronous ATPGetRequest calls can be canceled only by issuing the ATPCloseSocket
  17182. call, but that will cancel all outstanding calls for that socket.
  17183.  
  17184. •••Refer to Technical Note #250:•••
  17185.  
  17186. Warning:  You cannot reuse a variable of type ABusRecord passed to an ATP
  17187.           routine until the entire transaction has either been completed
  17188.           or canceled.
  17189.  
  17190. »ATP Routines
  17191.  
  17192. FUNCTION ATPLoad :  OSErr; [Not in ROM]
  17193.  
  17194. •••Refer to Technical Note #224:•••
  17195.  
  17196. ATPLoad first verifies that the .MPP driver is loaded and running. If it isn’t,
  17197. ATPLoad verifies that port B is configured for AppleTalk and isn’t in use, and then
  17198. loads MPP into the system heap.
  17199.  
  17200. ATPLoad then loads the .ATP driver, unless it’s already in memory. On a Macintosh
  17201. 128K, ATPLoad reads the .ATP driver from the system resource file into the application
  17202. heap; on a Macintosh 512K or XL, ATP is read into the system heap.
  17203.  
  17204. Note:  On a Macintosh 512K or XL, ATPLoad and MPPOpen perform essentially
  17205.        the same function.
  17206.  
  17207. Result codes    noErr        No error
  17208.                 portInUse    Port B is already in use
  17209.                 portNotCf    Port B not configured for AppleTalk
  17210.  
  17211. FUNCTION ATPUnload :  OSErr; [Not in ROM]
  17212.  
  17213. ATPUnload makes the .ATP driver purgeable; the space isn’t actually released by the
  17214. Memory Manager until necessary.
  17215.  
  17216. Note:  This call applies only to a Macintosh 128K; on a Macintosh 512K
  17217.        or Macintosh XL, ATPUnload has no effect.
  17218.  
  17219. Result codes    noErr    No error
  17220.  
  17221. FUNCTION ATPOpenSocket (addrRcvd:  AddrBlock;
  17222.                         VAR atpSocket:  Byte) :  OSErr; [Not in ROM]
  17223.  
  17224. ATPOpenSocket opens a socket for the purpose of receiving requests. ATPSocket contains
  17225. the socket number of the socket to open; if it’s 0, a number is dynamically assigned
  17226. and returned in atpSocket. AddrRcvd contains a filter of the sockets from which
  17227. requests will be accepted. A 0 in the network number, node ID, or socket number field
  17228. of the addrRcvd record acts as a “wild card”; for instance, a 0 in the socket number
  17229. field means that requests will be accepted from all sockets in the node(s) specified
  17230. by the network and node fields.
  17231.  
  17232. Result codes    noErr          No error
  17233.                 tooManySkts    Socket table full
  17234.                 noDataArea     Too many outstanding ATP calls
  17235.  
  17236. Note:  If you’re only going to send requests and receive responses to
  17237.        these requests, you don’t need to open an ATP socket. When you
  17238.        make the ATPSndRequest or ATPRequest call, ATP automatically
  17239.        opens a dynamically assigned socket for that purpose.
  17240.  
  17241. FUNCTION ATPCloseSocket (atpSocket:  Byte) :  OSErr; [Not in ROM]
  17242.  
  17243. ATPCloseSocket closes the responding socket whose number is specified by atpSocket.
  17244. It releases the data structures associated with all pending, asynchronous calls
  17245. involving that socket; these pending calls are completed immediately and return the
  17246. result code sktClosed.
  17247.  
  17248. Result codes    noErr         No error
  17249.                 noDataArea    Too many outstanding ATP calls
  17250.  
  17251. FUNCTION ATPSndRequest (abRecord:  ABRecHandle;
  17252.                         async:  BOOLEAN) :  OSErr; [Not in ROM]
  17253.  
  17254. ABusRecord
  17255.   <--    abOpcode         {always tATPSndRequest}
  17256.   <--    abResult         {result code}
  17257.   -->    abUserReference  {for your use}
  17258.   -->    atpAddress       {destination socket address}
  17259.   -->    atpReqCount      {request size in bytes}
  17260.   -->    atpDataPtr       {pointer to buffer}
  17261.   -->    atpRspBDSPtr     {pointer to response BDS}
  17262.   -->    atpUserData      {user bytes}
  17263.   -->    atpXO            {exactly-once flag}
  17264.   <--    atpEOM           {end-of-message flag}
  17265.   -->    atpTimeOut       {retry timeout interval in seconds}
  17266.   -->    atpRetries       {maximum number of retries}
  17267.   -->    atpNumBufs       {number of elements in response BDS}
  17268.   <--    atpNumRsp        {number of response packets actually received}
  17269.  
  17270. ATPSndRequest sends a request to another socket. ATPAddress is the internet address
  17271. of the socket to which the request should be sent. ATPDataPtr and atpReqCount specify
  17272. the location and size of a buffer that contains the request information to be sent.
  17273. ATPUserData contains the user bytes for the ATP header.
  17274.  
  17275. ATPSndRequest requires you to allocate a response BDS. ATPRspBDSPtr is a pointer to
  17276. the response BDS; atpNumBufs indicates the number of elements in the BDS (this is
  17277. also the maximum number of response datagrams that will be accepted). The number of
  17278. response datagrams actually received is returned in atpNumRsp; if a nonzero value is
  17279. returned, you can examine the response BDS to determine which packets of the transaction
  17280. were actually received. If the number returned is less than requested, one of the
  17281. following is true:
  17282.  
  17283.   •  Some of the packets have been lost and the retry count has been exceeded.
  17284.   •  ATPEOM is TRUE; this means that the response consisted of fewer packets
  17285.      than were expected, but that all packets sent were received (the last
  17286.      packet came with the atpEOM flag set).
  17287.  
  17288. ATPTimeOut indicates the length of time that ATPSndRequest should wait for a response
  17289. before retransmitting the request. ATPRetries indicates the maximum number of retries
  17290. ATPSndRequest should attempt. ATPXO should be TRUE if you want the request to be part
  17291. of an exactly-once transaction.
  17292.  
  17293. ATPSndRequest completes when either the transaction is completed or the retry count
  17294. is exceeded.
  17295.  
  17296. Result codes    noErr          No error
  17297.                 reqFailed      Retry count exceeded
  17298.                 tooManyReqs    Too many concurrent requests
  17299.                 noDataArea     Too many outstanding ATP calls
  17300.  
  17301. FUNCTION ATPRequest (abRecord:  ABRecHandle;
  17302.                      async:  BOOLEAN) :  OSErr; [Not in ROM]
  17303.  
  17304. ABusRecord
  17305.   <--    abOpcode         {always tATPRequest}
  17306.   <--    abResult         {result code}
  17307.   -->    abUserReference  {for your use}
  17308.   -->    atpAddress       {destination socket address}
  17309.   -->    atpReqCount      {request size in bytes}
  17310.   -->    atpDataPtr       {pointer to buffer}
  17311.   <--    atpActCount      {number of bytes actually received}
  17312.   -->    atpUserData      {user bytes}
  17313.   -->    atpXO            {exactly-once flag}
  17314.   <--    atpEOM           {end-of-message flag}
  17315.   -->    atpTimeOut       {retry timeout interval in seconds}
  17316.   -->    atpRetries       {maximum number of retries}
  17317.   <--    atpRspUData      {user bytes received in transaction response}
  17318.   -->    atpRspBuf        {pointer to response message buffer}
  17319.   -->    atpRspSize       {size of response message buffer}
  17320.  
  17321. ATPRequest is functionally analogous to ATPSndRequest. It sends a request to another
  17322. socket, but doesn’t require the caller to set up and use the BDS data structure to
  17323. describe the response buffers. ATPAddress indicates the socket to which the request
  17324. should be sent. ATPDataPtr and atpReqCount specify the location and size of a buffer
  17325. that contains the request information to be sent. ATPUserData contains the user bytes
  17326. to be sent in the request’s ATP header. ATPTimeOut indicates the length of time that
  17327. ATPRequest should wait for a response before retransmitting the request. ATPRetries
  17328. indicates the maximum number of retries ATPRequest should attempt.
  17329.  
  17330. To use this call, you must have an area of contiguous buffer space that’s large
  17331. enough to receive all expected datagrams. The various datagrams will be assembled in
  17332. this buffer and returned to you as a complete message upon completion of the transaction.
  17333. The location and size of this buffer are passed in atpRspBuf and atpRspSize. Upon
  17334. completion of the call, the size of the received response message is returned in
  17335. atpActCount. The user bytes received in the ATP header of the first response packet
  17336. are returned in atpRspUData. ATPXO should be TRUE if you want the request to be part
  17337. of an exactly-once transaction.
  17338.  
  17339. Although you don’t provide a BDS, ATPRequest in fact creates one and calls the
  17340. .ATP driver (as in an ATPSndRequest call). For this reason, the abRecord fields
  17341. atpRspBDSPtr and atpNumBufs are used by ATPRequest; you should not expect these
  17342. fields to remain unaltered during or after the function’s execution.
  17343.  
  17344. For ATPRequest to receive and correctly deliver the response as a single message, the
  17345. responding end must, upon receiving the request (with an ATPGetRequest call), generate
  17346. the complete response as a message in a single buffer and then call ATPResponse.
  17347.  
  17348. Note:  The responding end could also use ATPSndRsp and ATPAddRsp provided
  17349.        that each response packet (except the last one) contains exactly 578
  17350.        ATP data bytes; the last packet in the response can contain less than
  17351.        578 ATP data bytes. Also, if this method is used, only the ATP user
  17352.        bytes of the first response packet will be delivered to the requester;
  17353.        any information in the user bytes of the remaining response packets
  17354.        will not be delivered.
  17355.  
  17356. ATPRequest completes when either the transaction is completed or the retry count is
  17357. exceeded.
  17358.  
  17359. Result codes    noErr          No error
  17360.                 reqFailed      Retry count exceeded
  17361.                 tooManyReqs    Too many concurrent requests
  17362.                 sktClosed      Socket closed by a cancel call
  17363.                 noDataArea     Too many outstanding ATP calls
  17364.  
  17365. FUNCTION ATPReqCancel (abRecord:  ABRecHandle;
  17366.                        async:  BOOLEAN) :  OSErr; [Not in ROM]
  17367.  
  17368. Given the handle to the ABusRecord of a previously made ATPSndRequest or ATPRequest
  17369. call, ATPReqCancel dequeues the ATPSndRequest or ATPRequest call, provided that the
  17370. call hasn’t already completed. ATPReqCancel returns noErr if the ATPSndRequest or
  17371. ATPRequest call is successfully removed from the queue. If it returns cbNotFound,
  17372. check the abResult field of abRecord to verify that the ATPSndRequest or ATPRequest
  17373. call has completed and determine its outcome.
  17374.  
  17375. Result codes    noErr         No error
  17376.                 cbNotFound    ATP control block not found
  17377.  
  17378. FUNCTION ATPGetRequest (abRecord:  ABRecHandle;
  17379.                         async:  BOOLEAN) :  OSErr; [Not in ROM]
  17380.  
  17381. ABusRecord
  17382.   <--    abOpcode         {always tATPGetRequest}
  17383.   <--    abResult         {result code}
  17384.   -->    abUserReference  {for your use}
  17385.   -->    atpSocket        {listening socket number}
  17386.   <--    atpAddress       {source socket address}
  17387.   -->    atpReqCount      {buffer size in bytes}
  17388.   -->    atpDataPtr       {pointer to buffer}
  17389.   <--    atpBitMap        {transaction bit map}
  17390.   <--    atpTransID       {transaction ID}
  17391.   <--    atpActCount      {number of bytes actually received}
  17392.   <--    atpUserData      {user bytes}
  17393.   <--    atpXO            {exactly-once flag}
  17394.  
  17395. ATPGetRequest sets up the mechanism to receive a request sent by either an ATPSndRequest
  17396. or an ATPRequest call. ATPSocket contains the socket number of the socket that should
  17397. listen for a request; this socket must already have been opened by calling ATPOpenSocket.
  17398. The address of the socket from which the request was sent is returned in atpAddress.
  17399. ATPDataPtr specifies a buffer to store the incoming request; atpReqCount indicates
  17400. the size of the buffer in bytes. The number of bytes actually received in the request
  17401. is returned in atpActCount. ATPUserData contains the user bytes from the ATP header.
  17402. The transaction bit map is returned in atpBitMap. The transaction ID is returned in
  17403. atpTransID. ATPXO will be TRUE if the request is part of an exactly-once transaction.
  17404.  
  17405. ATPGetRequest completes when a request is received. To cancel an asynchronous ATPGetRequest
  17406. call, you must call ATPCloseSocket, but this cancels all pending calls involving that
  17407. socket.
  17408.  
  17409. Result codes    noErr        No error
  17410.                 badATPSkt    Bad responding socket
  17411.                 sktClosed    Socket closed by a cancel call
  17412.  
  17413. FUNCTION ATPSndRsp (abRecord:  ABRecHandle;
  17414.                     async:  BOOLEAN) :  OSErr; [Not in ROM]
  17415.  
  17416. ABusRecord
  17417.   <--    abOpcode         {always tATPSdRsp}
  17418.   <--    abResult         {result code}
  17419.   -->    abUserReference  {for your use}
  17420.   -->    atpSocket        {responding socket number}
  17421.   -->    atpAddress       {destination socket address}
  17422.   -->    atpRspBDSPtr     {pointer to response BDS}
  17423.   -->    atpTransID       {transaction ID}
  17424.   -->    atpEOM           {end-of-message flag}
  17425.   -->    atpNumBufs       {number of response packets being sent}
  17426.   -->    atpBDSSize       {number of elements in response BDS}
  17427.  
  17428. ATPSndRsp sends a response to another socket. ATPSocket contains the socket number
  17429. from which the response should be sent and atpAddress contains the internet address
  17430. of the socket to which the response should be sent. ATPTransID must contain the
  17431. transaction ID. ATPEOM is TRUE if the response BDS contains the final packet in a
  17432. transaction composed of a group of packets and the number of packets in the response
  17433. is less than expected. ATPRspBDSPtr points to the buffer data structure containing
  17434. the responses to be sent. ATPBDSSize indicates the number of elements in the response
  17435. BDS, and must be in the range 1 to 8. ATPNumBufs indicates the number of response
  17436. packets being sent with this call, and must be in the range 0 to 8.
  17437.  
  17438. Note:  In some situations, you may want to send only part (or possibly none)
  17439.        of your response message back immediately. For instance, you might be
  17440.        requested to send back seven disk blocks, but have only enough internal
  17441.        memory to store one block. In this case, set atpBDSSize to 7 (total
  17442.        number of response packets), atpNumBufs to 0 (number of response
  17443.        packets currently being sent), and call ATPSndRsp. Then as you read
  17444.        in one block at a time, call ATPAddRsp until all seven response
  17445.        datagrams have been sent.
  17446.  
  17447. During exactly-once transactions, ATPSndRsp won’t complete until the release packet
  17448. is received or the release timer expires.
  17449.  
  17450. Result codes    noErr         No error
  17451.                 badATPSkt     Bad responding socket
  17452.                 noRelErr      No release received
  17453.                 sktClosed     Socket closed by a cancel call
  17454.                 noDataArea    Too many outstanding ATP calls
  17455.                 badBuffNum    Bad sequence number
  17456.  
  17457. FUNCTION ATPAddRsp (abRecord:  ABRecHandle) :  OSErr; [Not in ROM]
  17458.  
  17459. ABusRecord
  17460.   <--    abOpcode         {always tATPAddRsp}
  17461.   <--    abResult         {result code}
  17462.   -->    abUserReference  {for your use}
  17463.   -->    atpSocket        {responding socket number}
  17464.   -->    atpAddress       {destination socket address}
  17465.   -->    atpReqCount      {buffer size in bytes}
  17466.   -->    atpDataPtr       {pointer to buffer}
  17467.   -->    atpTransID       {transaction ID}
  17468.   -->    atpUserData      {user bytes}
  17469.   -->    atpEOM           {end-of-message flag}
  17470.   -->    atpNumRsp        {sequence number}
  17471.  
  17472. ATPAddRsp sends one additional response packet to a socket that has already been sent
  17473. the initial part of a response via ATPSndRsp. ATPSocket contains the socket number
  17474. from which the response should be sent and atpAddress contains the internet address
  17475. of the socket to which the response should be sent. ATPTransID must contain the
  17476. transaction ID. ATPDataPtr and atpReqCount specify the location and size of a buffer
  17477. that contains the information to send; atpNumRsp is the sequence number of the response.
  17478. ATPEOM is TRUE if this response datagram is the final packet in a transaction composed
  17479. of a group of packets. ATPUserData contains the user bytes to be sent in this response
  17480. datagram’s ATP header.
  17481.  
  17482. Note:  No BDS is needed with ATPAddRsp because all pertinent information
  17483.        is passed within the record.
  17484.  
  17485. Result codes    noErr         No error
  17486.                 badATPSkt     Bad responding socket
  17487.                 badBuffNum    Bad sequence number
  17488.                 noSendResp    ATPAddRsp issued before ATPSndRsp
  17489.                 noDataArea    Too many outstanding ATP calls
  17490.  
  17491. FUNCTION ATPResponse (abRecord:  ABRecHandle;
  17492.                       async:  BOOLEAN) :  OSErr; [Not in ROM]
  17493.  
  17494. ABusRecord
  17495.   <--    abOpcode         {always tATPResponse}
  17496.   <--    abResult         {result code}
  17497.   -->    abUserReference  {for your use}
  17498.   -->    atpSocket        {responding socket number}
  17499.   -->    atpAddress       {destination socket address}
  17500.   -->    atpTransID       {transaction ID)
  17501.   -->    atpRspUData      {user bytes sent in transaction response}
  17502.   -->    atpRspBuf        {pointer to response message buffer}
  17503.   -->    atpRspSize       {size of response message buffer}
  17504.  
  17505. ATPResponse is functionally analogous to ATPSndRsp. It sends a response to another
  17506. socket, but doesn’t require the caller to provide a BDS. ATPAddress must contain the
  17507. complete network address of the socket to which the response should be sent (taken
  17508. from the data provided by an ATPGetRequest call). ATPTransID must contain the transaction
  17509. ID. ATPSocket indicates the socket from which the response should be sent (the socket
  17510. on which the corresponding ATPGetRequest was issued). ATPRspBuf points to the buffer
  17511. containing the response message; the size of this buffer must be passed in atpRspSize.
  17512. The four user bytes to be sent in the ATP header of the first response packet are
  17513. passed in atpRspUData. The last packet of the transaction response is sent with the
  17514. EOM flag set.
  17515.  
  17516. Although you don’t provide a BDS, ATPResponse in fact creates one and calls the .ATP
  17517. driver (as in an ATPSndRsp call). For this reason, the abRecord fields atpRspBDSPtr
  17518. and atpNumBufs are used by ATPResponse; you should not expect these fields to remain
  17519. unaltered during or after the function’s execution.
  17520.  
  17521. During exactly-once transactions ATPResponse won’t complete until the release packet
  17522. is received or the release timer expires.
  17523.  
  17524. Warning:  The maximum permissible size of the response message is 4624 bytes.
  17525.  
  17526. Result codes    noErr         No error
  17527.                 badATPSkt     Bad responding socket
  17528.                 noRelErr      No release received
  17529.                 atpLenErr     Response too big
  17530.                 sktClosed     Socket closed by a cancel call
  17531.                 noDataArea    Too many outstanding ATP calls
  17532.  
  17533. FUNCTION ATPRspCancel (abRecord:  ABRecHandle;
  17534.                        async:  BOOLEAN) :  OSErr; [Not in ROM]
  17535.  
  17536. Given the handle to the ABusRecord of a previously made ATPSndRsp or ATPResponse
  17537. call, ATPRspCancel dequeues the ATPSndRsp or ATPResponse call, provided that the call
  17538. hasn’t already completed. ATPRspCancel returns noErr if the ATPSndRsp or ATPResponse
  17539. call is successfully removed from the queue. If it returns cbNotFound, check the
  17540. abResult field of abRecord to verify that the ATPSndRsp or ATPResponse call has
  17541. completed and determine its outcome.
  17542.  
  17543. Result codes    noErr         No error
  17544.                 cbNotFound    ATP control block not found
  17545.  
  17546. »Example
  17547.  
  17548. This example shows the requesting side of an ATP transaction that asks for a 512-byte
  17549. disk block from the responding end. The block number of the file is a byte and is
  17550. contained in myBuffer[0].
  17551.  
  17552. VAR
  17553.   myABRecord: ABRecHandle;
  17554.   myBDSPtr: BDSPtr;
  17555.   myBuffer: PACKED ARRAY [0..511] OF CHAR;
  17556.   errCode: INTEGER;
  17557.   async: BOOLEAN;
  17558.  
  17559. BEGIN
  17560.   errCode := ATPLoad;
  17561.   IF errCode <> noErr THEN
  17562.     WRITELN('Error in opening AppleTalk')
  17563.     {Maybe serial port B isn't available for use by AppleTalk}
  17564.   ELSE
  17565.     BEGIN
  17566.       {Prepare the BDS; allocate space for a one-element BDS}
  17567.       myBDSPtr := BDSPtr(NewPtr(SIZEOF(BDSElement)));
  17568.       WITH myBDSPtr^[0] DO
  17569.         BEGIN
  17570.           buffSize := 512; {size of our buffer used in reception}
  17571.           buffPtr := @myBuffer; {pointer to the buffer}
  17572.         END;
  17573.       {Prepare the ABusRecord}
  17574.       myBuffer[0] := CHR(1); {requesting disk block number 1}
  17575.       myABRecord := ABRecHandle(NewHandle(atpSize));
  17576.       WITH myABRecord^^ DO
  17577.         BEGIN
  17578.           atpAddress.aNet := 0;
  17579.           atpAddress.aNode := 30; {we probably got this from an NBP call}
  17580.           atpAddress.aSocket := 15; {socket to send request to}
  17581.           atpReqCount := 1; {size of request data field (disk block #)}
  17582.           atpDataPtr := @myBuffer; {ptr to request to be sent}
  17583.           atpRspBDSPtr := @myBDSPtr;
  17584.           atpUserData := 0; {for your use}
  17585.           atpXO := FALSE; {at-least-once service}
  17586.           atpTimeOut := 5; {5-second timeout}
  17587.           atpRetries := 3; {3 retries; request will be sent 4 times max}
  17588.           atpNumBufs := 1; {we're only expecting 1 block to be returned}
  17589.         END;
  17590.       async := FALSE;
  17591.       {Send the request and wait for the response}
  17592.       errCode := ATPSndRequest(myABRecord, async);
  17593.       IF errCode <> noErr THEN
  17594.         WRITELN('An error occurred in the ATPSndRequest call')
  17595.       ELSE
  17596.         BEGIN
  17597.           {The disk block requested is now in myBuffer. We can verify }
  17598.           { that atpNumRsp contains 1, meaning one response received.}
  17599.         . . .
  17600.         END;
  17601.     END;
  17602. END.
  17603.  
  17604. _______________________________________________________________________________
  17605.  
  17606. »Name-Binding Protocol
  17607.  
  17608. »Data Structures
  17609.  
  17610. NBP calls use the following fields:
  17611.  
  17612. nbpProto:
  17613.   (nbpEntityPtr:       EntityPtr;     {pointer to entity name}
  17614.    nbpBufPtr:          Ptr;           {pointer to buffer}
  17615.    nbpBufSize:         INTEGER;       {buffer size in bytes}
  17616.    nbpDataField:       INTEGER;       {number of addresses or socket number}
  17617.    nbpAddress:         AddrBlock;     {socket address}
  17618.    nbpRetransmitInfo:  RetransType);  {retransmission information}
  17619.  
  17620. When data is sent via NBP, nbpBufSize indicates the size of the data in bytes and
  17621. nbpBufPtr points to a buffer containing the data. When data is received via NBP,
  17622. nbpBufPtr points to a buffer in which the incoming data can be stored and nbpBufSize
  17623. indicates the size of the buffer in bytes. NBPAddress is used in some calls to give
  17624. the internet address of a named entity. The AddrBlock data type is described above
  17625. under “Datagram Delivery Protocol”.
  17626.  
  17627. NBPEntityPtr points to a variable of type EntityName, which has the following data
  17628. structure:
  17629.  
  17630. TYPE  EntityName = RECORD
  17631.                      objStr:   Str32;   {object}
  17632.                      typeStr:  Str32;   {type}
  17633.                      zoneStr:  Str32    {zone}
  17634.                    END;
  17635.  
  17636.       EntityPtr = ^EntityName;
  17637.       Str32 = STRING[32];
  17638.  
  17639. NBPRetransmitInfo contains information about the number of times a packet should be
  17640. transmitted and the interval between retransmissions:
  17641.  
  17642. TYPE  RetransType =  PACKED RECORD
  17643.                        retransInterval:  Byte;    {retransmit interval in }
  17644.                                                   { 8-tick units}
  17645.                        retransCount:     Byte     {total number of attempts}
  17646.                      END;
  17647.  
  17648. RetransCount contains the total number of times a packet should be transmitted,
  17649. including the first transmission. If retransCount is 0, the packet will be transmitted
  17650. a total of 255 times.
  17651.  
  17652. »Using NBP
  17653.  
  17654. On a Macintosh 128K, the AppleTalk Manager’s NBP code is read into the application
  17655. heap when any one of the NBP (Pascal) routines is called; you can call the NBPLoad
  17656. function yourself if you want to load the NBP code explicitly. When you’re finished
  17657. with the NBP code and want to reclaim the space it occupies, call NBPUnload. On a
  17658. Macintosh 512K or XL, the NBP code is read in when the .MPP driver is loaded.
  17659.  
  17660. Note:  When another application starts up, the application heap is
  17661.        reinitialized; on a Macintosh 128K, this means that the NBP
  17662.        code is lost (and must be reloaded by the next application).
  17663.  
  17664. When an entity wants to communicate via an AppleTalk network, it should call NBPRegister
  17665. to place its name and internet address in the names table. When an entity no longer
  17666. wants to communicate on the network, or is being shut down, it should call NBPRemove
  17667. to remove its entry from the names table.
  17668.  
  17669. To determine the address of an entity you know only by name, call NBPLookup, which
  17670. returns a list of all entities with the name you specify. Call NBPExtract to extract
  17671. entity names from the list.
  17672.  
  17673. If you already know the address of an entity, and want only to confirm that it still
  17674. exists, call NBPConfirm. NBPConfirm is more efficient than NBPLookup in terms of
  17675. network traffic.
  17676.  
  17677. »NBP Routines
  17678.  
  17679. FUNCTION NBPRegister (abRecord:  ABRecHandle;
  17680.                       async:  BOOLEAN) :  OSErr; [Not in ROM]
  17681.  
  17682. ABusRecord
  17683.   <--    abOpcode            {always tNBPRegister}
  17684.   <--    abResult            {result code}
  17685.   -->    abUserReference     {for your use}
  17686.   -->    nbpEntityPtr        {pointer to entity name}
  17687.   -->    nbpBufPtr           {pointer to buffer}
  17688.   -->    nbpBufSize          {buffer size in bytes}
  17689.   -->    nbpAddress.aSocket  {socket address}
  17690.   -->    nbpRetransmitInfo   {retransmission information}
  17691.  
  17692. NBPRegister adds the name and address of an entity to the node’s names table. NBPEntityPtr
  17693. points to a variable of type EntityName containing the entity’s name. If the name is
  17694. already registered, NBPRegister returns the result code nbpDuplicate. NBPAddress
  17695. indicates the socket for which the name should be registered. NBPBufPtr and nbpBufSize
  17696. specify the location and size of a buffer for NBP to use internally.
  17697.  
  17698. While the variable of type EntityName is declared as three 32-byte strings, only the
  17699. actual characters of the name are placed in the buffer pointed to by nbpBufPtr. For
  17700. this reason, nbpBufSize needs only to be equal to the actual length of the name, plus
  17701. an additional 12 bytes for use by NBP.
  17702.  
  17703. Warning:  This buffer must not be altered or released until the name is
  17704.           removed from the names table via an NBPRemove call. If you
  17705.           allocate the buffer through a NewHandle call, you must lock
  17706.           it as long as the name is registered.
  17707.  
  17708. Warning:  The zone field of the entity name must be set to the
  17709.           meta-character “*”.
  17710.  
  17711. Result codes    noErr           No error
  17712.                 nbpDuplicate    Duplicate name already exists
  17713.  
  17714. FUNCTION NBPLookup (abRecord:  ABRecHandle;
  17715.                     async:  BOOLEAN) :  OSErr; [Not in ROM]
  17716.  
  17717. ABusRecord
  17718.   <--    abOpcode           {always tNBPLookup}
  17719.   <--    abResult           {result code}
  17720.   -->    abUserReference    {for your use}
  17721.   -->    nbpEntityPtr       {pointer to entity name}
  17722.   -->    nbpBufPtr          {pointer to buffer}
  17723.   -->    nbpBufSize         {buffer size in bytes}
  17724.   <->    nbpDataField       {number of addresses received}
  17725.   -->    nbpRetransmitInfo  {retransmission information}
  17726.  
  17727. NBPLookup returns the addresses of all entities with a specified name. NBPEntityPtr
  17728. points to a variable of type EntityName containing the name of the entity whose
  17729. address should be returned. (Meta-characters are allowed in the entity name.) NBPBufPtr
  17730. and nbpBufSize contain the location and size of an area of memory in which the entity
  17731. names and their corresponding addresses should be returned. NBPDataField indicates
  17732. the maximum number of matching names to find addresses for; the actual number of
  17733. addresses found is returned in nbpDataField. NBPRetransmitInfo contains the retry
  17734. interval and the retry count.
  17735.  
  17736. When specifying nbpBufSize, for each NBP tuple expected, allow space for the actual
  17737. characters of the name, the address, and four bytes for use by NBP.
  17738.  
  17739. Result codes    noErr         No error
  17740.                 nbpBuffOvr    Buffer overflow
  17741.  
  17742. FUNCTION NBPExtract (theBuffer:  Ptr; numInBuf:  INTEGER; whichOne:  INTEGER;
  17743.                      VAR abEntity:  EntityName;
  17744.                      VAR address:  AddrBlock) :  OSErr; [Not in ROM]
  17745.  
  17746. NBPExtract returns one address from the list of addresses returned by NBPLookup.
  17747. TheBuffer and numInBuf indicate the location and number of tuples in the buffer.
  17748. WhichOne specifies which one of the tuples in the buffer should be returned in the
  17749. abEntity and address parameters.
  17750.  
  17751. Result codes    noErr         No error
  17752.                 extractErr    Can’t find tuple in buffer
  17753.  
  17754. FUNCTION NBPConfirm (abRecord:  ABRecHandle;
  17755.                      async:  BOOLEAN) :  OSErr; [Not in ROM]
  17756.  
  17757. ABusRecord
  17758.   <--    abOpcode           {always tNBPConfirm}
  17759.   <--    abResult           {result code}
  17760.   -->    abUserReference    {for your use}
  17761.   -->    nbpEntityPtr       {pointer to entity name}
  17762.   <--    nbpDataField       {socket number}
  17763.   -->    nbpAddress         {socket address}
  17764.   -->    nbpRetransmitInfo  {retransmission information}
  17765.  
  17766. NBPConfirm confirms that an entity known by name and address still exists (is still
  17767. entered in the names directory). NBPEntityPtr points to a variable of type EntityName
  17768. that contains the name to confirm, and nbpAddress specifies the address to be confirmed.
  17769. (No meta-characters are allowed in the entity name.) NBPRetransmitInfo contains the
  17770. retry interval and the retry count. The socket number of the entity is returned in
  17771. nbpDataField. NBPConfirm is more efficient than NBPLookup in terms of network traffic.
  17772.  
  17773. Result codes    noErr           No error
  17774.                 nbpConfDiff     Name confirmed for different socket
  17775.                 nbpNoConfirm    Name not confirmed
  17776.  
  17777. FUNCTION NBPRemove (abEntity:  EntityPtr) :  OSErr; [Not in ROM]
  17778.  
  17779. NBPRemove removes an entity name from the names table of the given entity’s node.
  17780.  
  17781. Result codes    noErr          No error
  17782.                 nbpNotFound    Name not found
  17783.  
  17784. FUNCTION NBPLoad :  OSErr; [Not in ROM]
  17785.  
  17786. On a Macintosh 128K, NBPLoad reads the NBP code from the system resource file into
  17787. the application heap. On a Macintosh 512K or XL, NBPLoad has no effect since the NBP
  17788. code should have already been loaded when the .MPP driver was opened. Normally you’ll
  17789. never need to call NBPLoad, because the AppleTalk Manager calls it when necessary.
  17790.  
  17791. Result codes    noErr    No error
  17792.  
  17793. FUNCTION NBPUnload :  OSErr; [Not in ROM]
  17794.  
  17795. On a Macintosh 128K, NBPUnload makes the NBP code purgeable; the space isn’t actually
  17796. released by the Memory Manager until necessary. On a Macintosh 512K or Macintosh XL,
  17797. NBPUnload has no effect.
  17798.  
  17799. Result codes    noErr    No error
  17800.  
  17801. »Example
  17802.  
  17803. This example of NBP registers our node as a print spooler, searches for any print
  17804. spoolers registered on the network, and then extracts the information for the first
  17805. one found.
  17806.  
  17807. CONST
  17808.   mySocket = 20;
  17809.  
  17810. VAR
  17811.   myABRecord: ABRecHandle;
  17812.   myEntity: EntityName;
  17813.   entityAddr: AddrBlock;
  17814.   nbpNamePtr: Ptr;
  17815.   myBuffer: PACKED ARRAY [0..999] OF CHAR;
  17816.   errCode: INTEGER;
  17817.   async: BOOLEAN;
  17818.  
  17819. BEGIN
  17820.   errCode := MPPOpen;
  17821.   IF errCode <> noErr THEN
  17822.     WRITELN('Error in opening AppleTalk')
  17823.     {Maybe serial port B isn't available for use by AppleTalk}
  17824.   ELSE
  17825.     BEGIN
  17826.       {Call Memory Manager to allocate ABusRecord}
  17827.       myABRecord := ABRecHandle(NewHandle(nbpSize));
  17828.       {Set up our entity name to register}
  17829.       WITH myEntity DO
  17830.         BEGIN
  17831.           objStr := 'Gene Station'; {we are called 'Gene Station' }
  17832.           typeStr := 'PrintSpooler'; { and are of type 'PrintSpooler'}
  17833.           zoneStr := '*';
  17834.           {Allocate data space for the entity name (used by NBP)}
  17835.           nbpNamePtr := NewPtr(LENGTH(objStr) + LENGTH(typeStr) +
  17836.                                LENGTH(zoneStr) + 12);
  17837.         END;
  17838.       {Set up the ABusRecord for the NBPRegister call}
  17839.       WITH myABRecord^^ DO
  17840.         BEGIN
  17841.           nbpEntityPtr := @myEntity;
  17842.           nbpBufPtr := nbpNamePtr; {buffer used by NBP internally}
  17843.           nbpBufSize := nbpNameBufSize;
  17844.           nbpAddress.aSocket := mySocket; {socket to register us on}
  17845.           nbpRetransmitInfo.retransInterval := 8; {retransmit every 64 }
  17846.           nbpRetransmitInfo.retransCount := 3; { ticks and try 3 times}
  17847.         END;
  17848.       async := FALSE;
  17849.       errCode := NBPRegister(myABRecord, async);
  17850.       IF errCode <> noErr THEN
  17851.         WRITELN('Error occurred in the NBPRegister call')
  17852.         {Maybe the name is already registered somewhere else on the }
  17853.         { network.}
  17854.       ELSE
  17855.         BEGIN
  17856.           {Now that we've registered our name, find others of type }
  17857.           { 'PrintSpooler'.}
  17858.           WITH myEntity DO
  17859.             BEGIN
  17860.               objStr := '='; {any one of type }
  17861.               typeStr := 'PrintSpooler'; { “PrintSpooler” }
  17862.               zoneStr := '*'; { in our zone}
  17863.             END;
  17864.           WITH myABRecord^^ DO
  17865.             BEGIN
  17866.               nbpEntityPtr := @myEntity;
  17867.               nbpBufPtr := @myBuffer; {buffer to place responses in}
  17868.               nbpBufSize := SIZEOF(myBuffer);
  17869.              {The field nbpDataField, before the NBPLookup call, represents an }
  17870.               { approximate number of responses. After the call, nbpDataField }
  17871.               { contains the actual number of responses received.}
  17872.               nbpDataField := 100; {we want about 100 responses back}
  17873.             END;
  17874.           errCode := NBPLookup(myABRecord, async); {make sync call}
  17875.           IF errCode <> noErr THEN
  17876.             WRITELN('An error occurred in the NBPLookup')
  17877.             {Did the buffer overflow?}
  17878.           ELSE
  17879.             BEGIN
  17880.               {Get the first reply}
  17881.               errCode := NBPExtract(@mybuffer, myABRecord^^.nbpDataField, 1,
  17882.                                     myEntity, entityAddr);
  17883.            {The socket address and name of the entity are returned here. If we }
  17884.              { want all of them, we'll have to loop for each one in the buffer.}
  17885.               IF errCode <> noErr THEN WRITELN('Error in NBPExtract');
  17886.               {Maybe the one we wanted wasn't in the buffer}
  17887.             END;
  17888.         END;
  17889.     END;
  17890. END.
  17891.  
  17892. _______________________________________________________________________________
  17893.  
  17894. »Miscellaneous Routines
  17895.  
  17896. FUNCTION GetNodeAddress (VAR myNode,myNet:  INTEGER) :  OSErr; [Not in ROM]
  17897.  
  17898. GetNodeAddress returns the current node ID and network number of the caller. If the
  17899. .MPP driver isn’t installed, it returns noMPPErr. If myNet contains 0, this means
  17900. that a bridge hasn’t yet been found.
  17901.  
  17902. Result codes    noErr       No error
  17903.                 noMPPErr    MPP driver not installed
  17904.  
  17905. FUNCTION IsMPPOpen :  BOOLEAN; [Not in ROM]
  17906.  
  17907. IsMPPOpen returns TRUE if the .MPP driver is loaded and running.
  17908.  
  17909. FUNCTION IsATPOpen :  BOOLEAN; [Not in ROM]
  17910.  
  17911. IsATPOpen returns TRUE if the .ATP driver is loaded and running.
  17912.  
  17913. _______________________________________________________________________________
  17914.  
  17915.  
  17916. æKY New…AppleTalk…Manager…Pascal…Interface
  17917. æC »NEW APPLETALK MANAGER PASCAL INTERFACE                   AppleTalkManager
  17918. _______________________________________________________________________________
  17919.  
  17920. In addition to the interface documented in the previous section, a new parameter
  17921. block–style interface to the AppleTalk Manager is now available for Pascal programmers.
  17922. This new interface, referred to as the preferred interface, is available in addition
  17923. to the Pascal interface described in the previous section, which is referred to as
  17924. the alternate interface.  All AppleTalk Manager calls, old and new, are supported by
  17925. the preferred interface.
  17926.  
  17927. The alternate interface has not been extended to support the new AppleTalk Manager
  17928. calls.  However, the alternate interface provides the only implementation of LAPRead
  17929. and DDPRead. These are higher-level calls not directly supported through the assembly-language
  17930. interface.  Developers will wish to use the alternate interface for these calls, and
  17931. also for compatibility with previous applications.  In all other cases, it is recommended
  17932. that the new preferred interface be used.
  17933.  
  17934. _______________________________________________________________________________
  17935.  
  17936. »Using Pascal
  17937.  
  17938. All AppleTalk Manager calls in the  preferred interface are essentially equivalent to
  17939. the corresponding assembly-language calls.  Their form is
  17940.  
  17941. FUNCTION MPPCall (pbPtr: Ptr; asyncFlag: BOOLEAN) : OSErr;
  17942.  
  17943. where pbPtr points to a device manager parameter block, and asyncFlag is TRUE if the
  17944. call is to be executed asynchronously.  Three parameter block types are provided by
  17945. the preferred interface (MPP, ATP, and XPP).  The MPP parameter block is shown below.
  17946.  The ATP parameter block is shown in the following section, and the XPP parameter
  17947. block is shown in the “Calling the .XPP Driver” section of this document. The field
  17948. names in these parameter blocks are the same as the parameter block offset names
  17949. defined in the assembly-language section (except as documented below).  The caller
  17950. fills in the parameter block with the fields as specified in that section and issues
  17951. the appropriate call.  The interface issues the actual device manager control call.
  17952.  
  17953. On asynchronous calls, the caller may pass a completion routine pointer in the parameter
  17954. block, at offset ioCompletion.  This routine will be executed upon completion of the
  17955. call.  It is executed at interrupt level and must not make any memory manager calls. 
  17956. If it uses application globals, it must ensure that register A5 is set up correctly;
  17957. for details see SetupA5 and RestoreA5 in the Operating System Utilities chapter.  If
  17958. no completion routine is desired, ioCompletion should be set to NIL.
  17959.  
  17960. Asynchronous calls return control to the caller with result code of noErr as soon as
  17961. they are queued to the driver.  This isn’t an indication of successful completion. 
  17962. To determine when the call is actually completed, if you don’t want to use a completion
  17963. routine, you can poll the ioResult field; this field is set to 1 when the call is
  17964. made, and receives the actual result code upon completion.
  17965.  
  17966. Refer to the appropriate sections of this chapter for the parameter blocks used by
  17967. each MPP and ATP call.  As different MPP and ATP calls take different arguments in
  17968. their parameter block, two Pascal variant records have been defined to account for
  17969. all the different cases.  These parameter blocks are shown in the sections that
  17970. follow.  The first four fields (which are the same for all calls) are automatically
  17971. filled in by the device manager.  The csCode and ioRefnum fields are automatically
  17972. filled in by the interface, depending on which call is being made, except in XPP
  17973. where the caller must fill in the ioRefnum.  The ioVRefnum field is unused.
  17974.  
  17975. There are two fields that at the assembly-language level have more than one name. 
  17976. These two fields have been given only one name in the preferred interface.  These are
  17977. entityPtr and ntqelPtr, which are both referred to as entityPtr, and atpSocket and
  17978. currBitmap, which are both referred to as atpSocket. These are the only exceptions to
  17979. the naming convention.
  17980.  
  17981. »MPP Parameter Block
  17982.  
  17983. MPPParamBlock = PACKED RECORD
  17984.        qLink:          QElemPtr;     {next queue entry}
  17985.        qType:          INTEGER;      {queue type}
  17986.        ioTrap:         INTEGER;      {routine trap}
  17987.        ioCmdAddr:      Ptr;          {routine address}
  17988.        ioCompletion:   ProcPtr;      {completion routine}
  17989.        ioResult:       OSErr;        {result code}
  17990.        ioNamePtr:      StringPtr;    {command result (ATP user bytes) [long]}
  17991.        ioVRefNum:      INTEGER;      {volume reference or drive number}
  17992.        ioRefNum:       INTEGER;      {driver reference number}
  17993.        csCode:         INTEGER;      {call command code AUTOMATICALLY SET}
  17994.  
  17995.        CASE MPPParmType OF
  17996.        LAPWriteParm:
  17997.                     (filler0:INTEGER;
  17998.                     wdsPointer:Ptr);    {->Write Data Structure}
  17999.        AttachPHParm,DetachPHParm:
  18000.                     (protType:Byte;     {ALAP Protocol Type}
  18001.                     filler1:Byte;
  18002.                     handler:Ptr);       {->protocol handler routine}
  18003.        OpenSktParm,CloseSktParm,WriteDDPParm:
  18004.                     (socket:Byte;       {socket number}
  18005.                     checksumFlag:Byte;  {checksum flag}
  18006.                     listener:Ptr);      {->socket listener routine}
  18007.        RegisterNameParm,LookupNameParm,ConfirmNameParm,RemoveNameParm:
  18008.                     (interval:Byte;     {retry interval}
  18009.                     count:Byte;         {retry count}
  18010.                     entityPtr:Ptr;      {->names table element or }
  18011.                                         { ->entity name}
  18012.                     CASE MPPParmType OF
  18013.                     RegisterNameParm:
  18014.                              (verifyFlag:Byte;     {set if verify needed}
  18015.                               filler3:Byte);
  18016.                     LookupNameParm:
  18017.                                     (retBuffPtr:Ptr;       {->return buffer}
  18018.                                     retBuffSize:INTEGER;   {return buffer size}
  18019.                                     maxToGet:INTEGER;      {matches to get}
  18020.                                     numGotten:INTEGER);    {matched gotten}
  18021.                     ConfirmNameParm:
  18022.                                     (confirmAddr:AddrBlock; {->entity}
  18023.                                     newSocket:Byte;         {socket number}
  18024.                                     filler4:Byte));
  18025.  
  18026.        SetSelfSendParm:
  18027.                     (newSelfFlag:Byte;  {self-send toggle flag}
  18028.                     oldSelfFlag:Byte);  {previous self-send state}
  18029.        KillNBPParm:
  18030.                     (nKillQEl:Ptr);     {ptr to Q element to cancel}
  18031.      END;
  18032.  
  18033. »ATP Parameter Block
  18034.  
  18035. ATPParamBlock = PACKED RECORD
  18036.          qLink:            QElemPtr;    {next queue entry}
  18037.          qType:            INTEGER;     {queue type}
  18038.          ioTrap:           INTEGER;     {routine trap}
  18039.          ioCmdAddr:        Ptr;         {routine address}
  18040.          ioCompletion:     ProcPtr;     {completion routine}
  18041.          ioResult:         OSErr;       {result code}
  18042.          userData:         LONGINT;     {ATP user bytes [long]}
  18043.          reqTID:           INTEGER;     {request transaction ID}
  18044.          ioRefNum:         INTEGER;     {driver reference number
  18045.          csCode:           INTEGER;     {Call command code }
  18046.                                         { AUTOMATICALLY SET}
  18047.          atpSocket:        Byte;        {currBitMap or socket number}
  18048.          atpFlags:         Byte;        {control information}
  18049.          addrBlock:        AddrBlock;   {source/dest. socket address}
  18050.          reqLength:        INTEGER;     {request/response length}
  18051.          reqPointer:       Ptr;         {-> request/response data}
  18052.          bdsPointer:       Ptr;         {-> response BDS}
  18053.          CASE MPPParmType OF
  18054.                 SendRequestParm,NSendRequestParm:
  18055.                     (numOfBuffs:Byte;   {numOfBuffs}
  18056.                     timeOutVal:Byte;    {timeout interval}
  18057.                     numOfResps:Byte;    {number responses actually received}
  18058.                     retryCount:Byte;    {number of retries}
  18059.                     intBuff:INTEGER);   {used internally for NSendRequest}
  18060.                 SendResponseParm:
  18061.                     (filler0:Byte;      {number of responses being sent}
  18062.                     bdsSize:Byte;       {number of BDS elements}
  18063.                     transID:INTEGER);   {transaction ID}
  18064.                 GetRequestParm:
  18065.                     (bitMap:Byte;       {bit map}
  18066.                     filler1:Byte);
  18067.                 AddResponseParm:
  18068.                     (rspNum:Byte;       {sequence number}
  18069.                     filler2:Byte);
  18070.                 KillSendReqParm,KillGetReqParm:
  18071.                     (aKillQEl:Ptr);     {ptr to Q element to cancel}
  18072.          END;
  18073.  
  18074. The following table is a complete list of all the parameter block calls provided by
  18075. the preferred interface.
  18076.  
  18077. AppleTalk
  18078. Manager
  18079. Routine       Preferred Interface Call
  18080.  
  18081. AttachPH      Function PAttachPH (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18082. DetachPH      Function PDetachPH (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18083. WriteLAP      Function PWriteLAP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18084. OpenSkt       Function POpenSkt (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18085. CloseSkt      Function PCloseSkt (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18086. WriteDDP      Function PWriteDDP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18087. RegisterName  Function PRegisterName (thePBptr: MPPPBPtr;
  18088.                                       async: BOOLEAN) : OSErr;
  18089. LookupName    Function PLookupName (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18090. ConfirmName   Function PConfirmName (thePBptr: MPPPBPtr;
  18091.                                      async: BOOLEAN) : OSErr;
  18092. RemoveName    Function PRemoveName (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18093. OpenATPSkt    Function POpenATPSkt (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18094. CloseATPSkt   Function PCloseATPSkt (thePBptr: ATPPBPtr;
  18095.                                      async: BOOLEAN) : OSErr;
  18096. SendRequest   Function PSendRequest (thePBptr: ATPPBPtr;
  18097.                                      async: BOOLEAN) : OSErr;
  18098. GetRequest    Function PGetRequest (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18099. SendResponse  Function PSendResponse (thePBptr: ATPPBPtr;
  18100.                                       async: BOOLEAN) : OSErr;
  18101. AddResponse   Function PAddResponse(thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18102. ReltCB        Function PRelTCB (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18103. RelRspCB      Function PRelRspCB (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18104. SetSelfSend   Function PSetSelfSend (thePBptr: MPPPBPtr;
  18105.                                      async: BOOLEAN) : OSErr;
  18106. NSendRequest  Function PNSendRequest (thePBptr: ATPPBPtr;
  18107.                                       async: BOOLEAN) : OSErr;
  18108. KillSendReq   Function PKillSendReq (thePBptr: ATPPBPtr;
  18109.                                      async: BOOLEAN) : OSErr;
  18110. KillGetReq    Function PKillGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18111. KillNBP       Function PKillNBP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18112.  
  18113. _______________________________________________________________________________
  18114.  
  18115. »Building Data Structures
  18116.  
  18117. Because it is difficult for Pascal to deal with certain assembly-language structures,
  18118. the preferred interface provides a number of routines for building these structures. 
  18119. These routines are summarized below.
  18120.  
  18121. PROCEDURE BuildLAPwds (wdsPtr,dataPtr: Ptr;
  18122.                        destHost,protoType,frameLen: INTEGER);
  18123.  
  18124. This routine builds a single-frame write data structure LAP WDS for use with the
  18125. PWriteLAP call.  Given a buffer of length frameLen pointed to by dataPtr, it fills in
  18126. the WDS pointed to by wdsPtr and sets the destination node and protocol type as
  18127. indicated by destHost and protoType, respectively.  The WDS indicated must contain at
  18128. least two elements.
  18129.  
  18130. PROCEDURE BuildDDPwds  (wdsPtr,headerPtr,dataPtr: Ptr; destAddress: AddrBlock;
  18131.                         DDPType : INTEGER; dataLen: INTEGER);
  18132.  
  18133. This routine builds a single-frame write data structure  DDP WDS, for use with the
  18134. PWriteDDP call.  Given a header buffer of at least 17 bytes pointed to by headerPtr
  18135. and a data buffer of length dataLen pointed to by dataPtr, it fills in the WDS pointed
  18136. to by wdsPtr, and sets the destination address and protocol type as indicated by
  18137. destaddress and DDPtype, respectively.  The WDS indicated must contain at least 3
  18138. elements.
  18139.  
  18140. PROCEDURE NBPSetEntity (buffer: Ptr; nbpObject,nbpType,nbpZone: Str32);
  18141.  
  18142. This routine builds an NBP entity structure, for use with the PLookupNBP and PConfirmName
  18143. calls.  Given a buffer of at least the size of the EntityName data structure (99
  18144. bytes) pointed to by buffer, this routine sets the indicated object, type, and zone
  18145. in that buffer.
  18146.  
  18147. PROCEDURE NBPSetNTE (ntePtr: Ptr; nbpObject,nbpType,nbpZone: Str32;
  18148.                      Socket: INTEGER);
  18149.  
  18150. This routine builds an NBP names table entry, for use with the PRegisterName call. 
  18151. Given a names table entry of at least the size of the EntityName data structure plus
  18152. nine bytes (108 bytes) pointed to by ntePtr, this routine sets the indicated object,
  18153. type, zone, and socket in that names table entry.
  18154.  
  18155. FUNCTION NBPExtract (theBuffer: Ptr; numInBuf: INTEGER; whichOne: INTEGER; VAR abEntity:
  18156. EntityName; VAR address: AddrBlock) : OSErr;
  18157.  
  18158. This routine is provided in the alternate interface, but can be used as provided for
  18159. extracting NBP entity names from a look-up response buffer.
  18160.  
  18161. FUNCTION GetBridgeAddress: INTEGER;
  18162.  
  18163. This routine returns the current address of a bridge in the low byte, or zero if
  18164. there is none.
  18165.  
  18166. FUNCTION BuildBDS (buffPtr,bdsPtr: Ptr; buffSize: INTEGER) : INTEGER;
  18167.  
  18168. This routine builds a BDS, for use with the ATP calls.  Given a data buffer of length
  18169. buffSize pointed to by buffPtr, it fills in the BDS pointed to by bdsPtr.  The buffer
  18170. will be broken up into pieces of maximum size (578 bytes).  The user bytes in the BDS
  18171. are not modified by this routine.  This routine is provided only as a convenience;
  18172. generally the caller will be able to build the BDS completely from Pascal without
  18173. it.
  18174.  
  18175. _______________________________________________________________________________
  18176.  
  18177.  
  18178. æKY Picking…a…Node…Address…in…the…Server…Range
  18179. æC »PICKING A NODE ADDRESS IN THE SERVER RANGE               AppleTalkManager
  18180. _______________________________________________________________________________
  18181.  
  18182. Normally upon opening, the node number picked by the AppleTalk manager will be in the
  18183. node number range ($01–$7F).  It is possible to indicate that a node number in the
  18184. server range ($80–$FE) is desired.  Picking a number in the server range is a more
  18185. time-consuming but more thorough process, and it’s required for server nodes because
  18186. it greatly decreases the possibility of a node number conflict.
  18187.  
  18188. To open AppleTalk with a server node number, an extended open call is used.  An
  18189. extended open call is indicated by having the immediate bit set in the Open trap
  18190. itself.  In the extended open call, the high bit (bit 31) of the extension longword
  18191. field (ioMix) indicates whether a server or workstation node number should be picked.
  18192.  Set this bit to 1 to request a server node number.  The rest of this field should be
  18193. zero, as should all other unused fields in the queue element.   A server node number
  18194. can only be requested on the first Open call to the .MPP driver.
  18195.  
  18196. _______________________________________________________________________________
  18197.  
  18198.  
  18199. æKY Sending…Packets…to…One’s…Own…Node
  18200. æC »SENDING PACKETS TO ONE’S OWN NODE                        AppleTalkManager
  18201. _______________________________________________________________________________
  18202.  
  18203. Upon opening, the ability to send a packet to one’s own node (intranode delivery) is
  18204. disabled.  This feature of the AppleTalk Manager can be manipulated through the
  18205. SetSelfSend function.  Once enabled, it is possible, at all levels, to send packets
  18206. to entities within one’s own node.  An example of where this might be desirable is an
  18207. application sending data to a print spooler that is actually running in the background
  18208. on the same node.
  18209.  
  18210. Enabling (or disabling) this feature affects the entire node and should be performed
  18211. with care.  For instance, a desk accessory may not expect to receive names from
  18212. within its own node as a response to an NBP look-up;  enabling this feature from an
  18213. application could break the desk accessory.  All future programs should be written
  18214. with this feature in mind.
  18215.  
  18216. FUNCTION PSetSelfSend (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18217.  
  18218. Parameter Block
  18219.   -->    26    csCode         word    Always PSetSelfSend
  18220.   -->    28    newSelfFlag    byte    New SelfSend flag
  18221.   <--    29    oldSelfFlag    byte    Old SelfSend flag
  18222.  
  18223. PSetSelfSend enables or disables the intranode delivery feature of the AppleTalk
  18224. Manager.  If newSelfFlag is nonzero, the feature will be enabled; otherwise it will
  18225. be disabled.  The previous value of the flag will be returned in oldSelfFlag.
  18226.  
  18227. Result Codes    noErr        No error
  18228.  
  18229. _______________________________________________________________________________
  18230.  
  18231.  
  18232. æKY ATP…Driver…Changes
  18233. æC »ATP DRIVER CHANGES                                       AppleTalkManager
  18234. _______________________________________________________________________________
  18235.  
  18236. Changes to the ATP driver include the ability to send an ATP request through a specific
  18237. socket rather than having ATP open a new socket, a new call to abort outstanding
  18238. SendRequest calls, and a new call to abort specific outstanding GetRequest calls.
  18239.  
  18240. _______________________________________________________________________________
  18241.  
  18242. »Sending an ATP Request Through a Specified Socket
  18243.  
  18244. ATP requests can now be sent through client-specified sockets.  ATP previously would
  18245. open a dynamic socket, send the request through it, and close the socket when the
  18246. request was completed.  The client can now choose to send a request through an already-opened
  18247. socket; this also allows more than one request to be sent per socket.   A new call,
  18248. PNSendRequest, has been added for this purpose.  The function of the old SendRequest
  18249. call itself remains unchanged.
  18250.  
  18251. FUNCTION PNSendRequest (thePBptr: ATPBPtr; async: BOOLEAN) : OSErr;
  18252.  
  18253. Parameter block
  18254.   -->    18    userData     longword  User bytes
  18255.   <--    22    reqTID       word      Transaction ID used in request
  18256.   -->    26    csCode       word      Always sendRequest
  18257.   <->    28    atpSocket    byte      Socket to send request on
  18258.                                        or current bitmap
  18259.   <->    29    atpFlags     byte      Control information
  18260.   -->    30    addrBlock    longword  Destination socket address
  18261.   -->    34    reqLength    word      Request size in bytes
  18262.   -->    36    reqPointer   pointer   Pointer to request data
  18263.   -->    40    bdsPointer   pointer   Pointer to response BDS
  18264.   -->    44    numOfBuffs   byte      Number of responses expected
  18265.   -->    45    timeOutVal   byte      Timeout interval
  18266.   <--    46    numOf Resps  byte      Number of responses received
  18267.   <->    47    retryCount   byte      Number of retries
  18268.   <--    48    intBuff      word      Used internally
  18269.  
  18270. The PNSendRequest call is functionally equivalent to the SendRequest call, however
  18271. PNSendRequest allows you to specify, in the atpSocket field, the socket through which
  18272. the request is to be sent.  This socket must have been previously opened through an
  18273. OpenATPSkt request (otherwise a badATPSkt error will be returned).  Note that PNSendRequest
  18274. requires two additional bytes of memory at the end of the parameter block, immediately
  18275. following the retryCount.  These bytes are for the internal use of the AppleTalk
  18276. Manager and should not be modified while the PNSendRequest call is active.
  18277.  
  18278. There is a machine-dependent limit as to the number of concurrent PNSendRequests that
  18279. can be active on a given socket.  If this limit is exceeded, the error tooManyReqs is
  18280. returned.
  18281.  
  18282. One additional difference between SendRequest and PNSendRequest is that a PNSendRequest
  18283. can only be aborted by a PKillSendReq call (see below), whereas a SendRequest can be
  18284. aborted by either a RelTCB or KillSendReq call.
  18285.  
  18286. Result Codes    noErr          No error
  18287.                 reqFailed      Retry count exceeded
  18288.                 tooManyReqs    Too many concurrent requests
  18289.                 noDataArea     Too many outstanding ATP calls
  18290.                 reqAborted     Request cancelled by user
  18291.  
  18292. _______________________________________________________________________________
  18293.  
  18294. »Aborting ATP SendRequests
  18295.  
  18296. The  RelTCB call is still supported, but only for aborting SendRequests.  To abort
  18297. PNSendRequests, a new call, PKillSendReq, has been added.  This call will abort both
  18298. SendRequests and PNSendRequests.  PKillSendReq’s only argument is the queue element
  18299. pointer of the request to be aborted.  The queue element pointer is passed at the
  18300. offset of the PKillSendReq queue element specified by aKillQE1.
  18301.  
  18302. FUNCTION PKillSendReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18303.  
  18304. Parameter block
  18305.   -->    26    csCode    word     Always PKillSendReq
  18306.   -->    44    aKillQEl  pointer  Pointer to queue element
  18307.  
  18308. PKillSendReq is functionally equivalent to RelTCB, except that it takes different
  18309. arguments and will abort both SendRequests and PNSendRequests.  To abort one of these
  18310. calls, place a pointer to the queue element of the call to abort in aKillQEl and
  18311. issue the PKillSendReq call.
  18312.  
  18313. Result Codes    noErr          No error
  18314.                 cbNotFound     aKillQEl does not point to a SendReq
  18315.                                or NSendReq queue element
  18316.  
  18317. _______________________________________________________________________________
  18318.  
  18319. »Aborting ATP GetRequests
  18320.  
  18321. ATP GetRequests can now be aborted through the PKillGetReq call.  This call looks and
  18322. works just like the PKillSendReq call, and is used to abort a specific GetRequest
  18323. call.  Previously it was necessary to close the socket  to abort all GetRequest calls
  18324. on the socket.
  18325.  
  18326. FUNCTION PKillGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18327.  
  18328. Parameter block
  18329.   -->    26    csCode    word     Always PKillGetReq
  18330.   -->    44    aKillQEl  pointer  Pointer to queue element
  18331.  
  18332. PKillGetReq will abort a specific outstanding GetRequest call (as opposed to closing
  18333. the socket, which aborts all outstanding GetRequests on that socket).  The call will
  18334. be completed with a reqAborted error.  To abort a GetRequest, place a pointer to the
  18335. queue element of the call to abort in aKillQEl and issue the PKillGetReq call.
  18336.  
  18337. Result Codes    noErr         No error
  18338.                 cbNotFound    aKillQEl does not point to a GetReq
  18339.                               queue element
  18340.  
  18341. _______________________________________________________________________________
  18342.  
  18343.  
  18344. æKY Name…Binding…Protocol…Changes
  18345. æC »NAME BINDING PROTOCOL CHANGES                            AppleTalkManager
  18346. _______________________________________________________________________________
  18347.  
  18348. Changes to the Name Binding Protocol include supporting multiple concurrent requests
  18349. and a means for aborting an active request.
  18350.  
  18351. »Multiple Concurrent NBP Requests
  18352.  
  18353. NBP now supports multiple concurrent active requests.  Specifically, a number of
  18354. LookupNames, RegisterNames and ConfirmNames can all be active concurrently.  The
  18355. maximum number of  concurrent requests is machine dependent; if it is exceeded the
  18356. error tooManyReqs will be returned.  Active requests can be aborted by the PKillNBP
  18357. call.
  18358.  
  18359. »KillNBP function
  18360.  
  18361. FUNCTION PKillNBP (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18362.  
  18363. •••Refer to Technical Note #199:•••
  18364.  
  18365. Parameter block
  18366.   -->    26    csCode    word     Always PKillNBP
  18367.   -->    28    aKillQEl  pointer  Pointer to queue element
  18368.  
  18369. PKillNBP is used to abort an outstanding LookupName, RegisterName or ConfirmName
  18370. request.  To abort one of these calls, place a pointer to the queue element of the
  18371. call to abort in a KillQEl and issue the PKillNBP call.  The call will be completed
  18372. with a ReqAborted error.
  18373.  
  18374. Result Codes    noErr          No error
  18375.                 cbNotFound     aKillQEl does not point to a valid
  18376.                                NBP queue element
  18377.  
  18378. _______________________________________________________________________________
  18379.  
  18380.  
  18381. æKY Variable…Resources
  18382. æC »VARIABLE RESOURCES                                       AppleTalkManager
  18383. _______________________________________________________________________________
  18384.  
  18385. The table below lists machine-dependent resources for the different Macintosh system
  18386. configurations.  The RAM-based resources are available through the AppleShare Server.
  18387.  
  18388. Resource    Macintosh Plus    RAM-Based    Macintosh SE    Macintosh II
  18389.  
  18390. Protocol
  18391. Handlers           4             8              8               8
  18392.  
  18393. Statically
  18394. Assigned
  18395. Sockets           14*           12             12              14
  18396.  
  18397. Concurrent
  18398. ATP SendRequests   6            12             12              12
  18399.  
  18400. ATP Sockets        6            32             32             126
  18401.  
  18402. Concurrent
  18403. ATP Responses      8            16             16              32
  18404.  
  18405. Concurrent
  18406. NBP Requests       1             6              6              10
  18407.  
  18408. Concurrent
  18409. ASP Sessions      N/A            5             10              20
  18410.  
  18411. Concurrent
  18412. ATP NSendRequests
  18413. Per Socket **     N/A            9             14              62
  18414.  
  18415. * Includes dynamic sockets
  18416. **  Determined dynamically at runtime based on CPU speed.
  18417. N/A : Not Applicable
  18418.  
  18419. _______________________________________________________________________________
  18420.  
  18421.  
  18422. æKY Calling…the…AppleTalk…Manager…from…Assembly…Language
  18423. æC »CALLING THE APPLETALK MANAGER FROM ASSEMBLY LANGUAGE      AppleTalkManager
  18424. _______________________________________________________________________________
  18425.  
  18426. This section discusses how to use the AppleTalk Manager from assembly language.
  18427. Equivalent Pascal information is given in the preceding section.
  18428.  
  18429. All routines make Device Manager Control calls. The description of each routine
  18430. includes a list of the fields needed. Some of these fields are part of the parameter
  18431. block described in the Device Manager chapter; additional fields are provided for the
  18432. AppleTalk Manager.
  18433.  
  18434. The number next to each field name indicates the byte offset of the field from the
  18435. start of the parameter block pointed to by A0. An arrow next to each parameter name
  18436. indicates whether it’s an input, output, or input/output parameter:
  18437.  
  18438. Arrow    Meaning
  18439.   -->    Parameter is passed to the routine
  18440.   <--    Parameter is returned by the routine
  18441.   <->    Parameter is passed to and returned by the routine
  18442.  
  18443. All Device Manager Control calls return an integer result code of type OSErr in the
  18444. ioResult field. Each routine description lists all of the applicable result codes
  18445. generated by the AppleTalk Manager, along with a short description of what the result
  18446. code means. Lengthier explanations of all the result codes can be found in the summary
  18447. at the end of this chapter. Result codes from other parts of the Operating System may
  18448. also be returned. (See Appendix A for a list of all result codes.)
  18449.  
  18450. _______________________________________________________________________________
  18451.  
  18452. »Opening AppleTalk
  18453.  
  18454. •••Refer to Technical Note #224:•••
  18455.  
  18456. Two tests are made at system startup to determine whether the .MPP driver should be
  18457. opened at that time. If port B is already in use, or isn’t configured for AppleTalk,
  18458. .MPP isn’t opened until explicitly requested by an application; otherwise it’s opened
  18459. at system startup.
  18460.  
  18461. It’s the application’s responsibility to test the availability of port B before
  18462. opening AppleTalk. Assembly-language programmers can use the Pascal calls MPPOpen and
  18463. ATPLoad to open the .MPP and .ATP drivers.
  18464.  
  18465. The global variable SPConfig is used for configuring the serial ports; it’s copied
  18466. from a byte in parameter RAM (which is discussed in the Operating System Utilities
  18467. chapter). The low-order four bits of this variable contain the current configuration
  18468. of port B. The following use types are provided as global constants for testing or
  18469. setting the configuration of port B:
  18470.  
  18471.   useFree     .EQU    0    ;unconfigured
  18472.   useATalk    .EQU    1    ;configured for AppleTalk
  18473.   useAsync    .EQU    2    ;configured for the Serial Driver
  18474.  
  18475. The application shouldn’t attempt to open AppleTalk unless SPConfig is equal to
  18476. either useFree or useATalk.
  18477.  
  18478. A second test involves the global variable PortBUse; the low-order four bits of this
  18479. byte are used to monitor the current use of port B. If PortBUse is negative, the
  18480. program is free to open AppleTalk. If PortBUse is positive, the program should test
  18481. to see whether port B is already being used by AppleTalk; if it is, the low-order
  18482. four bits of PortBUse will be equal to the use type useATalk.
  18483.  
  18484. The .MPP driver sets PortBUse to the correct value (useATalk) when it’s opened and
  18485. resets it to $FF when it’s closed. Bits 4-6 of this byte are used for driver-specific
  18486. information; ATP uses bit 4 to indicate whether it’s currently opened:
  18487.  
  18488. atpLoadedBit    .EQU    4    ;set if ATP is opened
  18489.  
  18490. »Example
  18491.  
  18492. The following code illustrates the use of the SPConfig and PortBUse variables.
  18493.  
  18494.           MOVE      #-<atpUnitNum+1>,atpRefNum(A0)  ;save known ATP refNum in
  18495.                                                     ; case ATP not opened
  18496. OpenAbus  SUB       #ioQElSize,SP     ;allocate queue entry
  18497.           MOVE.L    SP,A0             ;A0 -> queue entry
  18498.           CLR.B     ioPermssn(A0)     ;make sure permission's clear
  18499.           MOVE.B    PortBUse,D1       ;is port B in use?
  18500.           BPL.S     @10               ;if so, make sure by AppleTalk
  18501.           MOVEQ     #portNotCf,D0     ;assume port not configured for AppleTalk
  18502.           MOVE.B    SPConfig,D1       ;get configuration data
  18503.           AND.B     #$0F,D1           ;mask it to low 4 bits
  18504.           SUBQ.B    #useATalk,D1      ;unconfigured or configured for AppleTalk
  18505.           BGT.S     @30               ;if not, return error
  18506.           LEA       mppName,A1        ;A1 = address of driver name
  18507.           MOVE.L    A1,ioFileName(A0) ;set in queue entry
  18508.           _Open                       ;open MPP
  18509.           BNE.S     @30               ;return error, if it can't load it
  18510.           BRA.S     @20               ;otherwise, go check ATP
  18511. @10       MOVEQ     #portInUse,D0     ;assume port in use error
  18512.           AND.B     #$0F,D1           ;clear all but use bits
  18513.           SUBQ.B    #useATalk,D1      ;is AppleTalk using it?
  18514.           BNE.S     @30               ;if not, then error
  18515. @20       MOVEQ     #0,D0             ;assume no error
  18516.           BTST      #atpLoadedBit,PortBUse    ;ATP already open?
  18517.           BNE.S     @30               ;just return if so
  18518.           LEA       atpName,A1        ;A1 = address of driver name
  18519.           MOVE.L    A1,ioFileName(A0) ;set in queue entry
  18520.           _Open                       ;open ATP
  18521. @30       ADD       #ioQElSize,SP     ;deallocate queue entry
  18522.           RTS                         ;and return
  18523. mppName   .BYTE     4                 ;length of .MPP driver name
  18524.           .ASCII    '.MPP'            ;name of .MPP driver
  18525. atpName   .BYTE     4                 ;length of .ATP driver name
  18526.           .ASCII    '.ATP'            ;name of .ATP driver
  18527.  
  18528. _______________________________________________________________________________
  18529.  
  18530. »AppleTalk Link Access Protocol
  18531.  
  18532. »Data Structures
  18533.  
  18534. An ALAP frame is composed of a three-byte header, up to 600 bytes of data, and a
  18535. two-byte frame check sequence (Figure 6). You can use the following global constants
  18536. to access the contents of an ALAP header:
  18537.  
  18538.   lapDstAdr  .EQU    0    ;destination node ID
  18539.   lapSrcAdr  .EQU    1    ;source node ID
  18540.   lapType    .EQU    2    ;ALAP protocol type
  18541.   lapHdSz    .EQU    3    ;ALAP header size
  18542.  
  18543. •••Refer to Figure 6.•••
  18544.  
  18545. Figure 6–ALAP Frame
  18546.  
  18547. Two of the protocol handlers in every node are used by DDP. These protocol handlers
  18548. service frames with ALAP protocol types equal to the following global constants:
  18549.  
  18550.   shortDDP   .EQU    1    ;short DDP header
  18551.   longDDP    .EQU    2    ;long DDP header
  18552.  
  18553. When you call ALAP to send a frame, you pass it information about the frame in a
  18554. write data structure, which has the format shown in Figure 7.
  18555.  
  18556. •••Refer to Figure 7.•••
  18557.  
  18558. Figure 7–Write Data Structure for ALAP
  18559.  
  18560. If you specify a destination node ID of 255, the frame will be broadcast to all
  18561. nodes. The byte that’s “used internally” is used by the AppleTalk Manager to store
  18562. the address of the node sending the frame.
  18563.  
  18564. »Using ALAP
  18565.  
  18566. Most programs will never need to call ALAP, because higher-level protocols will
  18567. automatically call ALAP as necessary. If you do want to send a frame directly via an
  18568. ALAP, call the WriteLAP function. There’s no ReadLAP function in assembly language;
  18569. if you want to read ALAP frames, you must call AttachPH to add your protocol handler
  18570. to the node’s protocol handler table. The ALAP module will examine every incoming
  18571. frame and call your protocol handler for each frame received with the correct ALAP
  18572. protocol. When your program no longer wants to receive frames with a particular ALAP
  18573. protocol type value, it can call DetachPH to remove the corresponding protocol handler
  18574. from the protocol handler table.
  18575.  
  18576. See the “Protocol Handlers and Socket Listeners” section for information on how to
  18577. write a protocol handler.
  18578.  
  18579. »ALAP Routines
  18580.  
  18581. WriteLAP function
  18582.  
  18583. Parameter block
  18584.   -->    26    csCode      word     ;always writeLAP
  18585.   -->    30    wdsPointer  pointer  ;write data structure
  18586.  
  18587. WriteLAP sends a frame to another node. The frame data and destination of the frame
  18588. are described by the write data structure pointed to by wdsPointer. The first two
  18589. data bytes of an ALAP frame sent to another computer using the AppleTalk Manager must
  18590. indicate the length of the frame in bytes. The ALAP protocol type byte must be in the
  18591. range 1 to 127.
  18592.  
  18593. Result codes    noErr            No error
  18594.                 excessCollsns    No CTS received after 32 RTS’s
  18595.                 ddpLengthErr     Packet length exceeds maximum
  18596.                 lapProtErr       Invalid ALAP protocol type
  18597.  
  18598. AttachPH function
  18599.  
  18600. Parameter block
  18601.   -->    26    csCode    word     ;always attachPH
  18602.   -->    28    protType  byte     ;ALAP protocol type
  18603.   -->    30    handler   pointer  ;protocol handler
  18604.  
  18605. AttachPH adds the protocol handler pointed to by handler to the node’s protocol
  18606. table. ProtType specifies what kind of frame the protocol handler can service. After
  18607. AttachPH is called, the protocol handler is called for each incoming frame whose ALAP
  18608. protocol type equals protType.
  18609.  
  18610. Result codes    noErr         No error
  18611.                 lapProtErr    Error attaching protocol type
  18612.  
  18613. DetachPH function
  18614.  
  18615. Parameter block
  18616.   -->    26    csCode    word  ;always detachPH
  18617.   -->    28    protType  byte  ;ALAP protocol type
  18618.  
  18619. DetachPH removes from the node’s protocol table the specified ALAP protocol type and
  18620. corresponding protocol handler.
  18621.  
  18622. Result codes    noErr         No error
  18623.                 lapProtErr    Error detaching protocol type
  18624.  
  18625. _______________________________________________________________________________
  18626.  
  18627. »Datagram Delivery Protocol
  18628.  
  18629. »Data Structures
  18630.  
  18631. A DDP datagram consists of a header followed by up to 586 bytes of actual data
  18632. (Figure 8). The headers can be of two different lengths; they’re identified by the
  18633. following ALAP protocol types:
  18634.  
  18635.   shortDDP   .EQU    1    ;short DDP header
  18636.   longDDP    .EQU    2    ;long DDP header
  18637.  
  18638. •••Refer to Figure 8.•••
  18639.  
  18640. Figure 8–DDP Datagram
  18641.  
  18642. Long DDP headers (13 bytes) are used for sending datagrams between two or more different
  18643. AppleTalk networks. You can use the following global constants to access the contents
  18644. of a long DDP header:
  18645.  
  18646.   ddpHopCnt    .EQU    0    ;count of bridges passed (4 bits)
  18647.   ddpLength    .EQU    0    ;datagram length (10 bits)
  18648.   ddpChecksum  .EQU    2    ;checksum
  18649.   ddpDstNet    .EQU    4    ;destination network number
  18650.   ddpSrcNet    .EQU    6    ;source network number
  18651.   ddpDstNode   .EQU    8    ;destination node ID
  18652.   ddpSrcNode   .EQU    9    ;source node ID
  18653.   ddpDstSkt    .EQU    10   ;destination socket number
  18654.   ddpSrcSkt    .EQU    11   ;source socket number
  18655.   ddpType      .EQU    12   ;DDP protocol type
  18656.  
  18657. The size of a DDP long header is given by the following constant:
  18658.  
  18659.   ddpHSzLong   .EQU    ddpType+1
  18660.  
  18661. The short headers (five bytes) are used for datagrams sent to sockets within the same
  18662. network as the source socket. You can use the following global constants to access
  18663. the contents of a short DDP header:
  18664.  
  18665.   ddpLength    .EQU    0               ;datagram length
  18666.   sDDPDstSkt   .EQU    ddpChecksum     ;destination socket number
  18667.   sDDPSrcSkt   .EQU    sDDPDstSkt+1    ;source socket number
  18668.   sDDPType     .EQU    sDDPSrcSkt+1    ;DDP protocol type
  18669.  
  18670. The size of a DDP short header is given by the following constant:
  18671.  
  18672.   ddpHSzShort  .EQU    sDDPType+1
  18673.  
  18674. The datagram length is a ten-bit field. You can use the following global constant as
  18675. a mask for these bits:
  18676.  
  18677.   ddpLenMask   .EQU    $03FF
  18678.  
  18679. The following constant indicates the maximum length of a DDP datagram:
  18680.  
  18681.   ddpMaxData   .EQU    586
  18682.  
  18683. When you call DDP to send a datagram, you pass it information about the datagram in a
  18684. write data structure with the format shown in Figure 9.
  18685.  
  18686. •••Refer to Figure 9.•••
  18687.  
  18688. Figure 9–Write Data Structure for DDP
  18689.  
  18690. The first seven bytes are used internally for the ALAP header and the DDP datagram
  18691. length and checksum. The other bytes used internally store the network number, node
  18692. ID, and socket number of the socket client sending the datagram.
  18693.  
  18694. Warning:  The first entry in a DDP write data structure must begin at
  18695.           an odd address.
  18696.  
  18697. If you specify a node ID of 255, the datagram will be broadcast to all nodes within
  18698. the destination network. A network number of 0 means the local network to which the
  18699. node is connected.
  18700.  
  18701. Warning:  DDP always destroys the high-order byte of the destination
  18702.           network number when it sends a datagram with a short header.
  18703.           Therefore, if you want to reuse the first entry of a DDP write
  18704.           data structure entry, you must restore the destination network number.
  18705.  
  18706. »Using DDP
  18707.  
  18708. Before it can use a socket, the program must call OpenSkt, which adds a socket and
  18709. its socket listener to the socket table. When a client is finished using a socket,
  18710. call CloseSkt, which removes the socket’s entry from the socket table. To send a
  18711. datagram via DDP, call WriteDDP. If you want to read DDP datagrams, you must write
  18712. your own socket listener. DDP will send every incoming datagram for that socket to
  18713. your socket listener.
  18714.  
  18715. See the “Protocol Handlers and Socket Listeners” section for information on how to
  18716. write a socket listener.
  18717.  
  18718. »DDP Routines
  18719.  
  18720. OpenSkt function
  18721.  
  18722. Parameter block
  18723.   -->    26    csCode    word     ;always openSkt
  18724.   <->    28    socket    byte     ;socket number
  18725.   -->    30    listener  pointer  ;socket listener
  18726.  
  18727. OpenSkt adds a socket and its socket listener to the socket table. If the socket
  18728. parameter is nonzero, it must be in the range 64 to 127, and it specifies the socket’s
  18729. number; if socket is 0, OpenSkt opens a socket with a socket number in the range 128
  18730. to 254, and returns it in the socket parameter. Listener contains a pointer to the
  18731. socket listener.
  18732.  
  18733. OpenSkt will return ddpSktErr if you pass the number of an already opened socket, if
  18734. you pass a socket number greater than 127, or if the socket table is full (the socket
  18735. table can hold a maximum of 12 sockets).
  18736.  
  18737. Result codes    noErr        No error
  18738.                 ddpSktErr    Socket error
  18739.  
  18740. CloseSkt function
  18741.  
  18742. Parameter block
  18743.   -->    26    csCode  word  ;always closeSkt
  18744.   -->    28    socket  byte  ;socket number
  18745.  
  18746. CloseSkt removes the entry of the specified socket from the socket table. If you pass
  18747. a socket number of 0, or if you attempt to close a socket that isn’t open, CloseSkt
  18748. will return ddpSktErr.
  18749.  
  18750. Result codes    noErr        No error
  18751.                 ddpSktErr    Socket error
  18752.  
  18753. WriteDDP function
  18754.  
  18755. Parameter block
  18756.   -->    26    csCode        word     ;always writeDDP
  18757.   -->    28    socket        byte     ;socket number
  18758.   -->    29    checksumFlag  byte     ;checksum flag
  18759.   -->    30    wdsPointer    pointer  ;write data structure
  18760.  
  18761. WriteDDP sends a datagram to another socket. WDSPointer points to a write data structure
  18762. containing the datagram and the address of the destination socket. If checksumFlag is
  18763. TRUE, WriteDDP will compute the checksum for all datagrams requiring long headers.
  18764.  
  18765. Result codes    noErr          No error
  18766.                 ddpLenErr      Datagram length too big
  18767.                 ddpSktErr      Socket error
  18768.                 noBridgeErr    No bridge found
  18769.  
  18770. _______________________________________________________________________________
  18771.  
  18772. »AppleTalk Transaction Protocol
  18773.  
  18774. »Data Structures
  18775.  
  18776. An ATP packet consists of an ALAP header, DDP header, and ATP header, followed by
  18777. actual data (Figure 10). You can use the following global constants to access the
  18778. contents of an ATP header:
  18779.  
  18780.   atpControl   .EQU    0    ;control information
  18781.   atpBitMap    .EQU    1    ;bit map
  18782.   atpRespNo    .EQU    1    ;sequence number
  18783.   atpTransID   .EQU    2    ;transaction ID
  18784.   atpUserData  .EQU    4    ;user bytes
  18785.  
  18786. The size of an ATP header is given by the following constant:
  18787.  
  18788.   atpHdSz      .EQU    8
  18789.  
  18790. •••Refer to Figure 10.•••
  18791.  
  18792. Figure 10–ATP Packet
  18793.  
  18794. ATP packets are identified by the following DDP protocol type:
  18795.  
  18796.   atp          .EQU    3
  18797.  
  18798. The control information contains a function code and various control bits. The function
  18799. code identifies either a TReq, TResp, or TRel packet with one of the following global
  18800. constants:
  18801.  
  18802.   atpReqCode   .EQU    $40    ;TReq packet
  18803.   atpRspCode   .EQU    $80    ;TResp packet
  18804.   atpRelCode   .EQU    $C0    ;TRel packet
  18805.  
  18806. The send-transmission-status, end-of-message, and exactly-once bits in the control
  18807. information are accessed via the following global constants:
  18808.  
  18809.   atpSTSBit    .EQU    3    ;send-transmission-status bit
  18810.   atpEOMBit    .EQU    4    ;end-of-message bit
  18811.   atpXOBit     .EQU    5    ;exactly-once bit
  18812.  
  18813. Many ATP calls require a field called atpFlags (Figure 11), which contains the above
  18814. three bits plus the following two bits:
  18815.  
  18816.   sendChk      .EQU    0    ;send-checksum bit
  18817.   tidValid     .EQU    1    ;transaction ID validity bit
  18818.  
  18819. •••Refer to Figure 11.•••
  18820.  
  18821. Figure 11–ATPFlags Field
  18822.  
  18823. The maximum number of response packets in an ATP transaction is given by the following
  18824. global constant:
  18825.  
  18826.   atpMaxNum    .EQU    8
  18827.  
  18828. When you call ATP to send responses, you pass the responses in a response BDS, which
  18829. is a list of up to eight elements, each of which contains the following:
  18830.  
  18831.   bdsBuffSz    .EQU    0    ;size of data to send
  18832.   bdsBuffAddr  .EQU    2    ;pointer to data
  18833.   bdsUserData  .EQU    8    ;user bytes
  18834.  
  18835. When you call ATP to receive responses, you pass it a response BDS with up to eight
  18836. elements, each in the following format:
  18837.  
  18838.   bdsBuffSz    .EQU    0    ;buffer size in bytes
  18839.   bdsBuffAddr  .EQU    2    ;pointer to buffer
  18840.   bdsDataSz    .EQU    6    ;number of bytes actually received
  18841.   bdsUserData  .EQU    8    ;user bytes
  18842.  
  18843. The size of a BDS element is given by the following constant:
  18844.  
  18845.   bdsEntrySz   .EQU    12
  18846.  
  18847. ATP clients are identified by internet addresses in the form shown in Figure 12.
  18848.  
  18849. •••Refer to Figure 12.•••
  18850.  
  18851. Figure 12–Internet Address
  18852.  
  18853. »Using ATP
  18854.  
  18855. Before you can use ATP on a Macintosh 128K, the .ATP driver must be read from the
  18856. system resource file via a Device Manager Open call. The name of the .ATP driver is
  18857. '.ATP' and its reference number is –11. When the .ATP driver is opened, it reads its
  18858. ATP code into the application heap and installs a task into the vertical retrace
  18859. queue.
  18860.  
  18861. Warning:  When another application starts up, the application heap is
  18862.           reinitialized; on a Macintosh 128K, this means that the ATP
  18863.           code is lost (and must be reloaded by the next application).
  18864.  
  18865. When you’re through using ATP on a Macintosh 128K, call the Device Manager Close
  18866. routine—the system will be returned to the state it was in before the
  18867. .ATP driver was opened.
  18868.  
  18869. On a Macintosh 512K or XL, the .ATP driver will have been loaded into the system heap
  18870. either at system startup or upon execution of a Device Manager Open call loading MPP.
  18871. You shouldn’t close the .ATP driver on a Macintosh 512K or XL; AppleTalk expects it
  18872. to remain open on these systems.
  18873.  
  18874. To send a request to another socket and get a response, call SendRequest. The call
  18875. terminates when either an entire response is received or a specified retry timeout
  18876. interval elapses. To open a socket for the purpose of responding to requests, call
  18877. OpenATPSkt. Then call GetRequest to receive a request; when a request is received,
  18878. the call is completed. After receiving and servicing a request, call SendResponse to
  18879. return response information. If you cannot or do not want to send the entire response
  18880. all at once, make a SendResponse call to send some of the response, and then call
  18881. AddResponse later to send the remainder of the response. To close a socket opened for
  18882. the purpose of sending responses, call CloseATPSkt.
  18883.  
  18884. During exactly-once transactions, SendResponse doesn’t terminate until the transaction
  18885. is completed via a TRel packet, or the retry count is exceeded.
  18886.  
  18887. Warning:  Don’t modify the parameter block passed to an ATP call until
  18888.           the call is completed.
  18889.  
  18890. »ATP Routines
  18891.  
  18892. OpenATPSkt function
  18893.  
  18894. Parameter block
  18895.   -->    26    csCode     word       ;always openATPSkt
  18896.   <->    28    atpSocket  byte       ;socket number
  18897.   -->    30    addrBlock  long word  ;socket request specification
  18898.  
  18899. OpenATPSkt opens a socket for the purpose of receiving requests. ATPSocket contains
  18900. the socket number of the socket to open. If it’s 0, a number is dynamically assigned
  18901. and returned in atpSocket. AddrBlock contains a specification of the socket addresses
  18902. from which requests will be accepted. A 0 in the network number, node ID, or socket
  18903. number field of addrBlock means that requests will be accepted from every network,
  18904. node, or socket, respectively.
  18905.  
  18906. Result codes    noErr          No error
  18907.                 tooManySkts    Too many responding sockets
  18908.                 noDataArea     Too many outstanding ATP calls
  18909.  
  18910. CloseATPSkt function
  18911.  
  18912. Parameter block
  18913.   -->    26    csCode     word    ;always closeATPSkt
  18914.   -->    28    atpSocket  byte    ;socket number
  18915.  
  18916. CloseATPSkt closes the socket whose number is specified by atpSocket, for the purpose
  18917. of receiving requests.
  18918.  
  18919. Result codes    noErr         No error
  18920.                 noDataArea    Too many outstanding ATP calls
  18921.  
  18922. SendRequest function
  18923.  
  18924. Parameter block
  18925.   -->    18    userData    long word  ;user bytes
  18926.   <--    22    reqTID      word       ;transaction ID used in request
  18927.   -->    26    csCode      word       ;always sendRequest
  18928.   <--    28    currBitMap  byte       ;bit map
  18929.   <->    29    atpFlags    byte       ;control information
  18930.   -->    30    addrBlock   long word  ;destination socket address
  18931.   -->    34    reqLength   word       ;request size in bytes
  18932.   -->    36    reqPointer  pointer    ;pointer to request data
  18933.   -->    40    bdsPointer  pointer    ;pointer to response BDS
  18934.   -->    44    numOfBuffs  byte       ;number of responses expected
  18935.   -->    45    timeOutVal  byte       ;timeout interval
  18936.   <--    46    numOfResps  byte       ;number of responses received
  18937.   <->    47    retryCount  byte       ;number of retries
  18938.  
  18939. SendRequest sends a request to another socket and waits for a response. UserData
  18940. contains the four user bytes. AddrBlock indicates the socket to which the request
  18941. should be sent. ReqLength and reqPointer contain the size and location of the request
  18942. to send. BDSPointer points to a response BDS where the responses are to be returned;
  18943. numOfBuffs indicates the number of responses requested. The number of responses
  18944. received is returned in numOfResps. If a nonzero value is returned in numOfResps, you
  18945. can examine currBitMap to determine which packets of the transaction were actually
  18946. received and to detect pieces for higher-level recovery, if desired.
  18947.  
  18948. TimeOutVal indicates the number of seconds that SendRequest should wait for a response
  18949. before resending the request. RetryCount indicates the maximum number of retries
  18950. SendRequest should attempt. The end-of-message flag of atpFlags will be set if the
  18951. EOM bit is set in the last packet received in a valid response sequence. The exactly-once
  18952. flag should be set if you want the request to be part of an exactly-once transaction.
  18953.  
  18954. To cancel a SendRequest call, you need the transaction ID; it’s returned in reqTID.
  18955. You can examine reqTID before the completion of the call, but its contents are valid
  18956. only after the tidValid bit of atpFlags has been set.
  18957.  
  18958. SendRequest completes when either an entire response is received or the retry count
  18959. is exceeded.
  18960.  
  18961. Note:  The value provided in retryCount will be modified during SendRequest
  18962.        if any retries are made. This field is used to monitor the number of
  18963.        retries; for each retry, it’s decremented by 1.
  18964.  
  18965. Result codes    noErr          No error
  18966.                 reqFailed      Retry count exceeded
  18967.                 tooManyReqs    Too many concurrent requests
  18968.                 noDataArea     Too many outstanding ATP calls
  18969.                 reqAborted     Request canceled by user
  18970.  
  18971. GetRequest function
  18972.  
  18973. Parameter block
  18974.   <--    18    userData    long word  ;user bytes
  18975.   -->    26    csCode      word       ;always getRequest
  18976.   -->    28    atpSocket   byte       ;socket number
  18977.   <--    29    atpFlags    byte       ;control information
  18978.   <--    30    addrBlock   long word  ;source of request
  18979.   <->    34    reqLength   word       ;request buffer size
  18980.   -->    36    reqPointer  pointer    ;pointer to request buffer
  18981.   <--    44    bitMap      byte       ;bit map
  18982.   <--    46    transID     word       ;transaction ID
  18983.  
  18984. GetRequest sets up the mechanism to receive a request sent by a SendRequest call.
  18985. UserData returns the four user bytes from the request. ATPSocket contains the socket
  18986. number of the socket that should listen for a request. The internet address of the
  18987. socket from which the request was sent is returned in addrBlock. ReqLength and reqPointer
  18988. indicate the size (in bytes) and location of a buffer to store the incoming request.
  18989. The actual size of the request is returned in reqLength. The transaction bit map and
  18990. transaction ID will be returned in bitMap and transID. The exactly-once flag in
  18991. atpFlags will be set if the request is part of an exactly-once transaction.
  18992.  
  18993. GetRequest completes when a request is received.
  18994.  
  18995. Result codes    noErr        No error
  18996.                 badATPSkt    Bad responding socket
  18997.  
  18998. SendResponse function
  18999.  
  19000. Parameter block
  19001.   <--    18    userData    long word  ;user bytes from TRel
  19002.   <--    22    reqTID      word       ;transaction ID used in request
  19003.   -->    26    csCode      word       ;always sendResponse
  19004.   -->    28    atpSocket   byte       ;socket number
  19005.   -->    29    atpFlags    byte       ;control information
  19006.   -->    30    addrBlock   long word  ;response destination
  19007.   -->    40    bdsPointer  pointer    ;pointer to response BDS
  19008.   -->    44    numOfBuffs  byte       ;number of response packets being sent
  19009.   -->    45    bdsSize     byte       ;BDS size in elements
  19010.   -->    46    transID     word       ;transaction ID
  19011.  
  19012. SendResponse sends a response to a socket. If the response was part of an exactly-once
  19013. transaction, userData will contain the user bytes from the TRel packet. ATPSocket
  19014. contains the socket number from which the response should be sent. The end-of-message
  19015. flag in atpFlags should be set if the response contains the final packet in a transaction
  19016. composed of a group of packets and the number of responses is less than requested.
  19017. AddrBlock indicates the address of the socket to which the response should be sent.
  19018. BDSPointer points to a response BDS containing room for the maximum number of responses
  19019. to be sent; bdsSize contains this maximum number. NumOfBuffs contains the number of
  19020. response packets to be sent in this call; you may wish to make AddResponse calls to
  19021. complete the response. TransID indicates the transaction ID of the associated request.
  19022.  
  19023. During exactly-once transactions, SendResponse doesn’t complete until either a TRel
  19024. packet is received from the socket that made the request, or the retry count is
  19025. exceeded.
  19026.  
  19027. Result codes    noErr         No error
  19028.                 badATPSkt     Bad responding socket
  19029.                 noRelErr      No release received
  19030.                 noDataArea    Too many outstanding ATP calls
  19031.                 badBuffNum    Sequence number out of range
  19032.  
  19033. AddResponse function
  19034.  
  19035. Parameter block
  19036.   -->    18    userData    long word  ;user bytes
  19037.   -->    26    csCode      word       ;always addResponse
  19038.   -->    28    atpSocket   byte       ;socket number
  19039.   -->    29    atpFlags    byte       ;control information
  19040.   -->    30    addrBlock   long word  ;response destination
  19041.   -->    34    reqLength   word       ;response size
  19042.   -->    36    reqPointer  pointer    ;pointer to response
  19043.   -->    44    rspNum      byte       ;sequence number
  19044.   -->    46    transID     word       ;transaction ID
  19045.  
  19046. AddResponse sends an additional response packet to a socket that has already been
  19047. sent the initial part of a response via SendResponse. UserData contains the four user
  19048. bytes. ATPSocket contains the socket number from which the response should be sent.
  19049. The end-of-message flag in atpFlags should be set if this response packet is the
  19050. final packet in a transaction composed of a group of packets and the number of responses
  19051. is less than requested. AddrBlock indicates the socket to which the response should
  19052. be sent. ReqLength and reqPointer contain the size (in bytes) and location of the
  19053. response to send; rspNum indicates the sequence number of the response (in the range
  19054. 0 to 7). TransID must contain the transaction ID.
  19055.  
  19056. Warning:  If the transaction is part of an exactly-once transaction, the
  19057.           buffer used in the AddResponse call must not be altered or
  19058.           released until the corresponding SendResponse call has completed.
  19059.  
  19060. Result codes    noErr         No error
  19061.                 badATPSkt     Bad responding socket
  19062.                 noSendResp    AddResponse issued before SendResponse
  19063.                 badBuffNum    Sequence number out of range
  19064.                 noDataArea    Too many outstanding ATP calls
  19065.  
  19066. RelTCB function
  19067.  
  19068. Parameter block
  19069.   -->    26    csCode     word       ;always relTCB
  19070.   -->    30    addrBlock  long word  ;destination of request
  19071.   -->    46    transID    word       ;transaction ID of request
  19072.  
  19073. RelTCB dequeues the specified SendRequest call and returns the result code reqAborted
  19074. for the aborted call. The transaction ID can be obtained from the reqTID field of the
  19075. SendRequest queue entry; see the description of SendRequest for details.
  19076.  
  19077. Result codes    noErr         No error
  19078.                 cbNotFound    ATP control block not found
  19079.                 noDataArea    Too many outstanding ATP calls
  19080.  
  19081. RelRspCB function
  19082.  
  19083. Parameter block
  19084.   -->    26    csCode     word      ;always relRspCB
  19085.   -->    28    atpSocket  byte      ;socket number that request was received on
  19086.   -->    30    addrBlock  long word ;source of request
  19087.   -->    46    transID    word      ;transaction ID of request
  19088.  
  19089. In an exactly-once transaction, RelRspCB cancels the specified SendResponse, without
  19090. waiting for the release timer to expire or a TRel packet to be received. No error is
  19091. returned for the SendResponse call. Whan called to cancel a transaction that isn’t
  19092. using exactly-once service, RelRspCB returns cbNotFound. The transaction ID can be
  19093. obtained from the reqTID field of the SendResponse queue entry; see the description
  19094. of SendResponse for details.
  19095.  
  19096. Result codes    noErr         No error
  19097.                 cbNotFound    ATP control block not found
  19098.  
  19099. _______________________________________________________________________________
  19100.  
  19101. »Name-Binding Protocol
  19102.  
  19103. »Data Structures
  19104.  
  19105. The first two bytes in the NBP header (Figure 13) indicate the type of the packet,
  19106. the number of tuples in the packet, and an NBP packet identifier. You can use the
  19107. following global constants to access these bytes:
  19108.  
  19109.   nbpControl  .EQU    0    ;packet type
  19110.   nbpTCount   .EQU    0    ;tuple count
  19111.   nbpID       .EQU    1    ;packet identifier
  19112.   nbpTuple    .EQU    2    ;start of first tuple
  19113.  
  19114. •••Refer to Figure 13.•••
  19115.  
  19116. Figure 13–NBP Packet
  19117.  
  19118. NBP packets are identified by the following DDP protocol type:
  19119.  
  19120.   nbp         .EQU    2
  19121.  
  19122. NBP uses the following global constants in the nbpControl field to identify NBP
  19123. packets:
  19124.  
  19125.   brRq        .EQU    1    ;broadcast request
  19126.   lkUp        .EQU    2    ;lookup request
  19127.   lkUpReply   .EQU    3    ;lookup reply
  19128.  
  19129. NBP entities are identified by internet address in the form shown in Figure 14 below.
  19130. Entities are also identified by tuples, which include both an internet address and an
  19131. entity name. You can use the following global constants to access information in
  19132. tuples:
  19133.  
  19134.   tupleNet    .EQU    0    ;network number
  19135.   tupleNode   .EQU    2    ;node ID
  19136.   tupleSkt    .EQU    3    ;socket number
  19137.   tupleEnum   .EQU    4    ;used internally
  19138.   tupleName   .EQU    5    ;entity name
  19139.  
  19140. The meta-characters in an entity name can be identified with the following global
  19141. constants:
  19142.  
  19143.   equals      .EQU    '='    ;“wild-card” meta-character
  19144.   star        .EQU    '*'    ;“this zone” meta-character
  19145.  
  19146. •••Refer to Figure 14.•••
  19147.  
  19148. Figure 14–Names Table Entry
  19149.  
  19150. The maximum number of tuples in an NBP packet is given by the following global constant:
  19151.  
  19152.   tupleMax    .EQU    15
  19153.  
  19154. Entity names are mapped to sockets via the names table. Each entry in the names table
  19155. has the structure shown in Figure 14.
  19156.  
  19157. You can use the following global constants to access some of the elements of a names
  19158. table entry:
  19159.  
  19160.   ntLink      .EQU    0    ;pointer to next entry
  19161.   ntTuple     .EQU    4    ;tuple
  19162.   ntSocket    .EQU    7    ;socket number
  19163.   ntEntity    .EQU    9    ;entity name
  19164.  
  19165. The socket number of the names information socket is given by the following global
  19166. constant:
  19167.  
  19168.   nis         .EQU    2
  19169.  
  19170. »Using NBP
  19171.  
  19172. On a Macintosh 128K, before calling any other NBP routines, call the LoadNBP function,
  19173. which reads the NBP code from the system resource file into the application heap.
  19174. (The NBP code is part of the .MPP driver, which has a driver reference number of
  19175. –10.) When you’re finished with NBP and want to reclaim the space its code occupies,
  19176. call UnloadNBP. On a Macintosh 512K or XL, the NBP code is read in when the .MPP
  19177. driver is loaded.
  19178.  
  19179. Warning:  When an application starts up, the application heap is
  19180.           reinitialized; on a Macintosh 128K, this means that the
  19181.           NBP code is lost (and must be reloaded by the next application).
  19182.  
  19183. When an entity wants to communicate via an AppleTalk network, it should call RegisterName
  19184. to place its name and internet address in the names table. When an entity no longer
  19185. wants to communicate on the network, or is being shut down, it should call RemoveName
  19186. to remove its entry from the names table.
  19187.  
  19188. To determine the address of an entity you know only by name, call LookupName, which
  19189. returns a list of all entities with the name you specify. If you already know the
  19190. address of an entity, and want only to confirm that it still exists, call ConfirmName.
  19191. ConfirmName is more efficient than LookupName in terms of network traffic.
  19192.  
  19193. »NBP Routines
  19194.  
  19195. RegisterName function
  19196.  
  19197. Parameter block
  19198.   -->    26    csCode      word     ;always registerName
  19199.   -->    28    interval    byte     ;retry interval
  19200.   <->    29    count       byte     ;retry count
  19201.   -->    30    ntQElPtr    pointer  ;names table element pointer
  19202.   -->    34    verifyFlag  byte     ;set if verify needed
  19203.  
  19204. RegisterName adds the name and address of an entity to the node’s names table. NTQElPtr
  19205. points to a names table entry containing the entity’s name and internet address (in
  19206. the form shown in Figure 14 above). Meta-characters aren’t allowed in the object and
  19207. type fields of the entity name; the zone field, however, must contain the meta-character
  19208. “*”. If verifyFlag is TRUE, RegisterName checks on the network to see if the name is
  19209. already in use, and returns a result code of nbpDuplicate if so. Interval and count
  19210. contain the retry interval in eight-tick units and the retry count. When a retry is
  19211. made, the count field is modified.
  19212.  
  19213. •••Refer to Technical Note #225:•••
  19214.  
  19215. Warning:  The names table entry passed to RegisterName remains the
  19216.           property of NBP until removed from the names table. Don’t
  19217.           attempt to remove or modify it. If you’ve allocated memory
  19218.           using a NewHandle call, you must lock it as long as the name
  19219.           is registered.
  19220.  
  19221. Warning:  VerifyFlag should normally be set before calling RegisterName.
  19222.  
  19223. Result codes    noErr           No error
  19224.                 nbpDuplicate    Duplicate name already exists
  19225.                 nbpNISErr       Error opening names information socket
  19226.  
  19227. LookupName function
  19228.  
  19229. Parameter block
  19230.   -->    26    csCode       word     ;always lookupName
  19231.   -->    28    interval     byte     ;retry interval
  19232.   <->    29    count        byte     ;retry count
  19233.   -->    30    entityPtr    pointer  ;pointer to entity name
  19234.   -->    34    retBuffPtr   pointer  ;pointer to buffer
  19235.   -->    38    retBuffSize  word     ;buffer size in bytes
  19236.   -->    40    maxToGet     word     ;matches to get
  19237.   <--    42    numGotten    word     ;matches found
  19238.  
  19239. LookupName returns the addresses of all entities with a specified name. EntityPtr
  19240. points to the entity’s name (in the form shown in Figure 14 above). Meta-characters
  19241. are allowed in the entity name. RetBuffPtr and retBuffSize contain the location and
  19242. size of an area of memory in which the tuples describing the entity names and their
  19243. corresponding addresses should be returned. MaxToGet indicates the maximum number of
  19244. matching names to find addresses for; the actual number of addresses found is returned
  19245. in numGotten. Interval and count contain the retry interval and the retry count.
  19246. LookupName completes when either the number of matches is equal to or greater than
  19247. maxToGet, or the retry count has been exceeded. The count field is decremented for
  19248. each retransmission.
  19249.  
  19250. Note:  NumGotten is first set to 0 and then incremented with each match
  19251.        found. You can test the value in this field, and can start examining
  19252.        the received addresses in the buffer while the lookup continues.
  19253.  
  19254. Result codes    noErr         No error
  19255.                 nbpBuffOvr    Buffer overflow
  19256.  
  19257. ConfirmName function
  19258.  
  19259. Parameter block
  19260.   -->    26    csCode       word     ;always confirmName
  19261.   -->    28    interval     byte     ;retry interval
  19262.   <->    29    count        byte     ;retry count
  19263.   -->    30    entityPtr    pointer  ;pointer to entity name
  19264.   -->    34    confirmAddr  pointer  ;entity address
  19265.   <--    38    newSocket    byte     ;socket number
  19266.  
  19267. ConfirmName confirms that an entity known by name and address still exists (is still
  19268. entered in the names directory). EntityPtr points to the entity’s name
  19269. (in the form shown in Figure 14 above). ConfirmAddr specifies the address to confirmed.
  19270. No meta-characters are allowed in the entity name. Interval and count contain the
  19271. retry interval and the retry count. The socket number of the entity is returned in
  19272. newSocket. ConfirmName is more efficient than LookupName in terms of network traffic.
  19273.  
  19274. Result codes    noErr           No error
  19275.                 nbpConfDiff     Name confirmed for different socket
  19276.                 nbpNoConfirm    Name not confirmed
  19277.  
  19278. RemoveName function
  19279.  
  19280. Parameter block
  19281.   -->    26    csCode     word     ;always removeName
  19282.   -->    30    entityPtr  pointer  ;pointer to entity name
  19283.  
  19284. RemoveName removes an entity name from the names table of the given entity’s node.
  19285.  
  19286. Result codes    noErr          No error
  19287.                 nbpNotFound    Name not found
  19288.  
  19289. LoadNBP function
  19290.  
  19291. Parameter block
  19292.   -->    26    csCode  word  ;always loadNBP
  19293.  
  19294. On a Macintosh 128K, LoadNBP reads the NBP code from the system resource file into
  19295. the application heap; on a Macintosh 512K or XL it has no effect.
  19296.  
  19297. Result codes    noErr    No error
  19298.  
  19299. UnloadNBP function
  19300.  
  19301. Parameter block
  19302.   -->    26    csCode  word  ;always unloadNBP
  19303.  
  19304. On a Macintosh 128K, UnloadNBP makes the NBP code purgeable; the space isn’t actually
  19305. released by the Memory Manager until necessary. On a Macintosh 512K or XL, UnloadNBP
  19306. has no effect.
  19307.  
  19308. Result codes    noErr    No error
  19309.  
  19310. _______________________________________________________________________________
  19311.  
  19312.  
  19313. æKY Extended…Protocol…Package…Driver
  19314. æC »EXTENDED PROTOCOL PACKAGE DRIVER                         AppleTalkManager
  19315. _______________________________________________________________________________
  19316.  
  19317. The Extended Protocol Package (XPP) driver is intended to implement several AppleTalk
  19318. communication protocols in the same package for ease of use.  The
  19319. .XPP driver currently consists of two modules that operate on two levels: the low-level
  19320. module implements the workstation side of AppleTalk Session Protocol, and the high-level
  19321. module implements a small portion of the workstation side of the AppleTalk Filing
  19322. Protocol.
  19323.  
  19324. This driver adds functionality to the AppleTalk manager by providing services additional
  19325. to those provided in the .MPP and .ATP drivers.  Figure 2 shows the Macintosh AppleTalk
  19326. drivers and the protocols accessible through each driver.
  19327.  
  19328. The .XPP driver maps an AFP call from the client workstation into one or more ASP
  19329. calls. .XPP provides one client-level call for AFP.
  19330.  
  19331. The implementation of AFP in the .XPP driver is very limited.  Most calls are a very
  19332. simple one-to-one mapping from an AFP call to an ASP command without any interpretation
  19333. of the syntax of the AFP command by the .XPP driver.  Refer to the “Mapping AFP
  19334. Commands” section of this chapter for further information.
  19335.  
  19336. _______________________________________________________________________________
  19337.  
  19338. »Version
  19339.  
  19340. The .XPP driver supports ASP Version (hex) $100, as described in Inside AppleTalk.
  19341.  
  19342. _______________________________________________________________________________
  19343.  
  19344. »Error Reporting
  19345.  
  19346. Errors are returned by the .XPP driver in the ioResult field of the Device Manager
  19347. Control calls.
  19348.  
  19349. The error conditions reported by the .XPP driver may represent the unsuccessful
  19350. completion of a routine in more than just one process involved in the interaction of
  19351. the session.   System-level, .XPP driver, AppleTalk, and server errors can all turn
  19352. up in the ioResult field.
  19353.  
  19354. AFP calls return codes indicating the unsuccessful completion of AFP commands in the
  19355. Command Result field of the parameter block (described below).
  19356.  
  19357. An application using the .XPP driver should  respond appropriately to error conditions
  19358. reported from the different parts of the interaction.  As shown in Figure 3, the
  19359. following errors can be returned in the ioResult field:
  19360.  
  19361.   1.  System-level errors
  19362.  
  19363.       System errors returned by the .XPP driver indicate such conditions
  19364.       as the driver not being open or a specific system call not being
  19365.       supported. For a complete list of result codes returned by the
  19366.       Macintosh system software, refer to Appendix A.
  19367.  
  19368.   2.  XPP errors (for example, “Session not opened”)
  19369.  
  19370.       The .XPP driver can also return errors resulting from its own
  19371.       activity (for example, the referenced session isn’t open).  The
  19372.       possible .XPP driver errors returned are listed in the .XPP driver
  19373.       results codes section with each function that can return the code.
  19374.  
  19375.   3.  AppleTalk Errors (returned from lower-level protocols)
  19376.  
  19377.       .XPP may also return errors from lower-level protocols (for example,
  19378.       “Socket not open”).  Possible error conditions and codes are described
  19379.       elsewhere in this chapter.
  19380.  
  19381.   4.  An  ASP-specific error could be returned from an ASP server in
  19382.       response to a failed OpenSession call.  Errors of this type, returned
  19383.       by the server to the workstation, are documented both in Inside
  19384.       AppleTalk, section 11,  “AppleTalk Session Protocol”, and in the .XPP
  19385.       driver results code section of this chapter.
  19386.  
  19387.   5.  The AppleTalk Filing Protocol defines errors that are returned from
  19388.       the server to the workstation client.  These errors are returned in
  19389.       the cmdResult field of the parameter block (error type 5 in Figure 15).
  19390.       This field is valid if no system-level error is returned by the call.
  19391.       Note that at the ASP level, the cmdResult field is client-defined data
  19392.       and may not be an error code.
  19393.  
  19394. •••Refer to Figure 15.•••
  19395.  
  19396. Figure 15–Error Reporting
  19397.  
  19398. _______________________________________________________________________________
  19399.  
  19400. ».XPP Driver Functions Overview
  19401.  
  19402. The paragraphs below describe the implementation of ASP in the .XPP driver.  For more
  19403. detailed information about ASP, refer to Inside AppleTalk, Section 11, “AppleTalk
  19404. Session Protocol (ASP)”.
  19405.  
  19406. »Using AppleTalk Name Binding Protocol
  19407.  
  19408. A server wishing to advertise its service on the AppleTalk network calls ATP to open
  19409. an ATP responding socket known as the session listening socket (SLS).  The server
  19410. then calls the Name Binding Protocol (NBP) to register a name on this socket.  At
  19411. this point, the server calls the server side of ASP to pass it the address of the
  19412. SLS.  Then,  the server starts listening on the SLS for session opening requests
  19413. coming over the network.
  19414.  
  19415. »Opening and Closing Sessions
  19416.  
  19417. When a workstation wishes to access a server, the workstation must call NBP to discover
  19418. the SLS for that server.  Then the workstation calls ASP to open a session with that
  19419. server.
  19420.  
  19421. After determining the SLS (address) of the server, the workstation client issues an
  19422. OpenSession (or AFPLogin) call to open a session with that server.  As a result of
  19423. this call, ASP sends a special OpenSession packet (an ATP request) to the SLS; this
  19424. packet carries the address of a workstation socket for use in the session.   This
  19425. socket is referred to as the workstation session socket (WSS).  If the server is
  19426. unable to set up the session, it returns an error.  If the request is successful, the
  19427. server returns no error, and the session is opened.  The open session packet also
  19428. contains a version number so that both ends can verify that they are speaking the
  19429. same version of ASP.
  19430.  
  19431. The AbortOS function can be used to abort an outstanding OpenSession request before
  19432. it has completed.
  19433.  
  19434. The workstation client closes the session by issuing a CloseSession (or AFPLogout). 
  19435. The CloseSession call aborts any calls that are active on the session and closes the
  19436. session.  The session can also be closed by the server or by ASP itself, such as when
  19437. one end of the session fails.  The CloseAll call (which should be used with care)
  19438. aborts every session that the driver has active.
  19439.  
  19440. »Session Maintenance
  19441.  
  19442. A session will remain open until it is explicitly terminated by the ASP client at
  19443. either end or until one of the sessions ends, fails, or becomes unreachable.
  19444.  
  19445. »Commands on an Open Session
  19446.  
  19447. Once a session has been opened, the workstation client can send a sequence of commands
  19448. over the session to the server end.  The commands are delivered in the same order as
  19449. they are issued at the workstation end, and replies to the commands are returned to
  19450. the workstation end.
  19451.  
  19452. Three types of commands can be made on an open session.  These commands are UserCommand,
  19453. UserWrite, and AFPCall functions described in the following paragraphs.
  19454.  
  19455. UserCommand calls are similar to ATP requests.  The workstation client sends a command
  19456. (included in a variable size command block) to the server client requesting it to
  19457. perform a particular function and send back a variable size command reply.  Examples
  19458. of such commands vary from a request to open a particular file on a file server, to
  19459. reading a certain range of bytes from a device.  In the first case, a small amount of
  19460. reply data is returned; in the second case a multiple-packet reply might be generated.
  19461.  
  19462. The .XPP driver does not interpret the command block or in any way participate in
  19463. executing the command’s function.  It simply conveys the command block, included in a
  19464. higher-level format, to the server end of the session, and returns the command reply
  19465. to the workstation-end client.  The command reply consists of a four-byte command
  19466. result and a variable size command reply block.
  19467.  
  19468. UserWrite allows the workstation to convey blocks of data to the server.  UserWrite
  19469. is used to transfer a variable size block of data to the server end of the session
  19470. and to receive a reply.
  19471.  
  19472. The AFPCall function provides a mechanism for passing an AFP command to the server
  19473. end of an open session and receiving a reply.  The first byte of the AFPCall command
  19474. buffer contains the code for the AFP command that is to be passed to the server for
  19475. execution.  Most AFP calls are implemented through a very simple one-to-one mapping
  19476. that takes the call and makes an ASP command out of it.
  19477.  
  19478. The AFPCall function can have one of four different, but very similar, formats.
  19479.  
  19480. »Getting Server Status Information
  19481.  
  19482. ASP provides a service to allow its workstation clients to obtain a block of service
  19483. status information from a server without the need for opening a session.   The GetStatus
  19484. function  returns a status block from the server identified by the indicated address.
  19485.  ASP does not impose any structure on the status block.  This structure is defined by
  19486. the protocol above ASP.
  19487.  
  19488. »Attention Mechanism
  19489.  
  19490. Attentions are defined in ASP as a way for the server to alert the workstation of
  19491. some event or critical piece of information.  The ASP OpenSession and AFPLogin calls
  19492. include a pointer to an attention routine in their parameter blocks.  This attention
  19493. routine is called by the .XPP driver when it receives an attention from the server
  19494. and also when the session is closing as described below.
  19495.  
  19496. In addition, upon receiving an OpenSession call or AFPLogin call, the .XPP driver
  19497. sets the first two bytes of the session control block (SCB) to zero.  When the .XPP
  19498. driver receives an attention, the first two bytes of the SCB are set to the attention
  19499. bytes from the packet (which are always nonzero).
  19500.  
  19501. Note: A higher-level language such as Pascal may not wish to have a low-level
  19502.       attention routine called.  A Pascal program can poll the attention bytes,
  19503.       and if they are ever nonzero, the program will know that an attention
  19504.       has come in.  (It would then set the attention bytes back to zero.)
  19505.       Of course, two or more attentions could be received between successive
  19506.       polls, and only the last one would be recorded.
  19507.  
  19508. The .XPP driver also calls the attention routine when the session is closed by either
  19509. the server, workstation, or ASP itself (if the ASP session times out).  In these
  19510. cases, the attention bytes in the SCB are unchanged.
  19511.  
  19512. »The Attention Routine
  19513.  
  19514. The attention routine is called at interrupt level and must observe interrupt conventions.
  19515. Specifically, the interrupt routine can change registers A0 through A3 and D0 through
  19516. D3 and it must not make any Memory Manager calls.
  19517.  
  19518. It will be called with
  19519.  
  19520.   •  D0 (word) equal to the SessRefnum for that session (see OpenSession
  19521.      Function)
  19522.   •  D1 (word) equal to the attention bytes passed by the server (or zero
  19523.      if the session is closing)
  19524.  
  19525. Return with an RTS (return from subroutine) to resume normal execution.
  19526.  
  19527. The next section describes the calls that can be made to the .XPP driver.
  19528.  
  19529. _______________________________________________________________________________
  19530.  
  19531.  
  19532. æKY Calling…the….XPP…Driver
  19533. æC »CALLING THE .XPP DRIVER                                  AppleTalkManager
  19534. _______________________________________________________________________________
  19535.  
  19536. This section describes how to use the .XPP driver and how to call the .XPP driver
  19537. routines from assembly language and Pascal.
  19538.  
  19539. _______________________________________________________________________________
  19540.  
  19541. »Using XPP
  19542.  
  19543. The .XPP driver implements the workstation side of ASP and provides a mechanism for
  19544. the workstation to send AppleTalk Filing Protocol (AFP) commands to the server.
  19545.  
  19546. »Allocating Memory
  19547.  
  19548. Every call to the .XPP driver requires the caller to pass in whatever memory is
  19549. needed by the driver for the call, generally at the end of the queue element. When a
  19550. session is opened, the memory required for maintenance of that session
  19551. (that is, the Session Control Block) is also passed in.
  19552.  
  19553. For standard Device Manager calls, a queue element of a specific size equal to IOQElSize
  19554. is allocated.  When issuing many calls to XPP, it is the caller’s responsibility to
  19555. allocate a queue element that is large enough to accommodate the .XPP driver’s requirements
  19556. for executing that call, as defined below.  Once allocated, that memory can’t be
  19557. modified until the call completes.
  19558.  
  19559. »Opening the .XPP Driver
  19560.  
  19561. To open the .XPP driver, issue a Device Manager Open call.  (Refer to the Device
  19562. Manager chapter.)  The name of the .XPP driver is '.XPP'.  The original Macintosh
  19563. ROMs require that .XPP be opened only once. With new ROMs, the .XPP unit number can
  19564. always be obtained through an Open call.  With old ROMs only, the .XPP unit number
  19565. must be hard coded to XPPUnitNum (40) since only one Open call can be issued to the
  19566. driver.
  19567.  
  19568. The .XPP driver cannot be opened unless AppleTalk is open.  The application must
  19569. ensure that the .MPP and .ATP drivers are opened, as described earlier in this chapter.
  19570.  
  19571. The xppLoaded bit (bit 5) in the PortBUse byte in low memory indicates whether or not
  19572. the .XPP driver is open.
  19573.  
  19574. »Example
  19575.  
  19576. The following is an example of the procedure an application might use to open the
  19577. .XPP driver.
  19578.  
  19579. ;    Routine: OpenXPP
  19580. ;
  19581. ;        Open the .XPP driver and return the driver refNum for it.
  19582. ;
  19583. ;        Exit:    D0 = error code (ccr's set)
  19584. ;                 D1 = XPP driver refNum (if no errors)
  19585. ;
  19586. ;        All other registers preserved
  19587. ;
  19588. xppUnitNum    EQU    40                 ;default XPP driver number
  19589. xppTfRNum     EQU    -(xppUnitNum+1)    ;default XPP driver refNum
  19590.  
  19591. OpenXPP
  19592.     MOVE.L    A0-A1/D2,-(SP)            ;save registers
  19593.     MOVE      ROM85,D0                  ;check ROM type byte
  19594.     BPL.S     @10                       ;branch if >=128K ROMs
  19595.     BTST      #xppLoadedBit,PortBUse    ;is the XPP driver open already?
  19596.     BEQ.S     @10                       ;if not open, then branch to Open code
  19597.     MOVE      #xppTfRNum,D1             ;else use this as driver refnum
  19598.     MOVEQ     #0,D0                     ;set noErr
  19599.     BRA.S     @90                       ;and exit
  19600. ;
  19601. ; XPP driver not open. Make an _Open call to it. If using a 128K
  19602. ; ROM machine and the driver is already open, we will make another
  19603. ; Open call to it just so we get the correct driver refNum.
  19604. ;
  19605. @10 SUB       #ioQElSize,SP             ;allocate temporary param block
  19606.     MOVE.L    SP,A0                     ;A0 -> param block
  19607.     LEA       XPPName, A1               ;A1 -> XPP (ASP/AFP) driver name
  19608.     MOVE.L    A1,ioFileName(A0)         ;driver name into param block
  19609.     CLR.B     ioPermssn(A0)             ;clear permissions byte
  19610.     _Open
  19611.     MOVE      ioRefNum(A0),D1           ;D1=driver refNum (invalid if error)
  19612.     ADD       #ioQElSize,SP             ;deallocate temp param block
  19613. @90 MOVE.L    (SP)+,A0-A1/D2            ;restore registers
  19614.     TST       D0                        ;error? (set ccr's)
  19615.     RTS
  19616.     
  19617. XPPName  DC.B  4                        ;length of string
  19618.          DC.B  '.XPP'                   ;driver name
  19619.  
  19620. From Pascal, XPP can be opened through the OpenXPP call, which returns the driver’s
  19621. reference number:
  19622.  
  19623. FUNCTION OpenXPP (VAR xppRefnum: INTEGER) : OSErr;
  19624.  
  19625. »Open Errors
  19626.  
  19627. Errors returned when calling the Device Manager Open routine if the function does not
  19628. execute properly include the following:
  19629.  
  19630.   •  errors returned by System
  19631.   •  portInUse is returned if the AppleTalk port is in use by a driver
  19632.      other than AppleTalk or if AppleTalk is not open.
  19633.  
  19634. »Closing the .XPP Driver
  19635.  
  19636. To close the .XPP driver, call the Device Manager Close routine.
  19637.  
  19638. Warning:  There is generally no reason to close the driver.  Use this
  19639.           call sparingly, if at all.  This call should generally be used
  19640.           only by system-level applications.
  19641.  
  19642. »Close Errors
  19643.  
  19644. Errors returned when calling the Device Manager Close routine if the function does
  19645. not execute properly include the following:
  19646.  
  19647.   •  errors returned by System
  19648.   •  closeErr (new ROMs only) is returned if you try to close the driver
  19649.      and there are sessions active through that driver.  When sessions are
  19650.      active, closeErr is returned and the driver remains open.
  19651.   •  on old ROMs the driver is closed whether or not sessions are active
  19652.      and no error is returned. Results are unpredictable if sessions are
  19653.      still active.
  19654.  
  19655. »Session Control Block
  19656.  
  19657. The session control block (SCB) is a nonrelocatable block of data passed by the
  19658. caller to XPP upon session opening. XPP reserves this block for use in maintaining an
  19659. open session.   The SCB size is defined by the constant scbMemSize.  The SCB is a
  19660. locked block, and as long as the session is open, the SCB cannot be modified in any
  19661. way by the application.  There is one SCB for each open session. This block can be
  19662. reused once a CloseSess call is issued and completed for that session or when the
  19663. session is indicated as closed.
  19664.  
  19665. _______________________________________________________________________________
  19666.  
  19667. »How to Access the .XPP Driver
  19668.  
  19669. This section contains information for programmers using Pascal and assembly-language
  19670. routines.
  19671.  
  19672. All .XPP driver routines can be executed either synchronously (meaning that the
  19673. application can’t continue until the routine is completed) or asynchronously
  19674. (meaning that the application is free to perform other tasks while the routine is
  19675. executing).
  19676.  
  19677. XPP calls are made from Pascal in the same manner as MPP and ATP calls, with the
  19678. exception that when making XPP calls the caller must set the XPP driver’s refnum.  
  19679. This refnum is returned in the XPPOpen call’s parameter block.
  19680.  
  19681. A Pascal variant record has been defined for all XPP calls.  This parameter block is
  19682. detailed in the “.XPP Driver Parameter Block Record” section below.  The first four
  19683. fields (which are the same for all calls) are automatically filled in by the device
  19684. manager.  The csCode field is automatically filled in by Pascal, depending on which
  19685. call is being made.  The caller must, however, set the ioRefnum field to XPP’s reference
  19686. number, as returned in the OpenXPP call.  The ioVRefnum field is unused.
  19687.  
  19688. Note that the parameter block is defined so as to be the maximum size used by any
  19689. call.  Different calls take different size parameter blocks, each call requiring a
  19690. certain minimum size.  Callers are free to abbreviate the parameter block where
  19691. appropriate.
  19692.  
  19693. »General
  19694.  
  19695. With each routine, a list of the parameter block fields used by the call is also
  19696. given.  All routines are invoked by Device Manager Control calls with the csCode
  19697. field equal to the code corresponding to the function being called.  The number next
  19698. to each field name indicates the byte offset of the field from the start of the
  19699. parameter block pointed to by A0; only assembly-language programmers need to be
  19700. concerned with it.  An arrow next to each parameter name indicates whether it’s an
  19701. input, output, or input/output parameter:
  19702.  
  19703. Arrow    Meaning
  19704.   <--    Parameter is passed
  19705.   <--    Parameter is returned
  19706.   <->    Parameter is passed and returned
  19707.  
  19708. All Device Manager Control calls return an integer result code in the ioResult field.
  19709.  Each routine description lists all the applicable result codes, along with a short
  19710. description of what the result code means.  Refer to the section
  19711. “XPP Driver Result Codes” for an alphabetical list of result codes returned by the
  19712. .XPP driver.
  19713.  
  19714. Each routine description includes a Pascal form of the call.   Pascal calls to the
  19715. .XPP Driver are of the form:
  19716.  
  19717. FUNCTION XPPCall (paramBlock: XPPParmBlkPtr,async: BOOLEAN) : OSErr;
  19718.  
  19719. XPPCall is the name of the routine.
  19720.  
  19721. The parameter paramBlock points to the actual I/O queue element used in the
  19722. _Control call, filled in by the caller with the parameters of the routine.
  19723.  
  19724. The parameter async indicates whether or not the call should be made asynchronously. 
  19725.  If async is TRUE, the call is executed asynchronously; otherwise the call is executed
  19726. synchronously.
  19727.  
  19728. The routine returns a result code of type OSErr.
  19729.  
  19730. ».XPP Driver Parameter Block Record
  19731.  
  19732. XPPParamBlock = PACKED RECORD
  19733.     qLink:         QElemPtr;  {next queue entry}
  19734.     qType:         INTEGER;   {queue type}
  19735.     ioTrap:        INTEGER;   {routine trap}
  19736.     ioCmdAddr:     Ptr;       {routine address}
  19737.     ioCompletion:  ProcPtr;   {completion routine}
  19738.     ioResult:      OSErr;     {result code}
  19739.     cmdResult:     LONGINT;   {command result (ATP user bytes) [long]}
  19740.     ioVRefNum:     INTEGER;   {volume reference or drive number)
  19741.     ioRefNum:      INTEGER;   {driver reference number)
  19742.     csCode:        INTEGER;   {Call command code}
  19743.     CASE XPPPrmBlkType OF
  19744.       ASPAbortPrm:
  19745.         (abortSCBPtr:    Ptr);      {SCB pointer for AbortOS [long]}
  19746.       ASPSizeBlk:
  19747.         (aspMaxCmdSize:  INTEGER;   {for SPGetParms [word]
  19748.         aspQuantumSize:  INTEGER;   {for SPGetParms [word]}
  19749.         numSesss:        INTEGER);  {for SPGetParms [word]}
  19750.       XPPPrmBlk:
  19751.         (sessRefnum:     INTEGER;   {offset to session refnum [word]}
  19752.         aspTimeout:      Byte;      {timeout for ATP [byte]}
  19753.         aspRetry:        Byte;      {retry count for ATP [byte]}
  19754.         CASE XPPSubPrmType OF
  19755.           ASPOpenPrm:
  19756.             (serverAddr:    AddrBlock;  {server address block [longword]}
  19757.             scbPointer:     Ptr;        {SCB pointer [longword]}
  19758.             attnRoutine:    Ptr);       {attention routine pointer [long]}
  19759.           ASPSubPrm:
  19760.             (cbSize:        INTEGER;    {command block size [word]}
  19761.             cbPtr:          Ptr;        {command block pointer [long]}
  19762.             rbSize:         INTEGER;    {reply buffer size [word]}
  19763.             rbPtr:          Ptr;        {reply buffer pointer [long]}
  19764.             CASE XPPEndPrmType OF
  19765.               AFPLoginPrm:
  19766.                 (afpAddrBlock:     AddrBlock;    {address block in}
  19767.                                                  { AFPlogin [long]}
  19768.                 afpSCBPtr:         Ptr;          {SCB pointer in }
  19769.                                                  { AFPlogin [long]}
  19770.                 afpAttnRoutine:    Ptr);         {attn routine pointer }
  19771.                                                  { in AFPlogin}
  19772.               ASPEndPrm:
  19773.                 (wdSize:           INTEGER;      {write data size [word]}
  19774.                 wdPtr:             Ptr;          {write data pointer [long]}
  19775.                 ccbStart:          ARRAY[0..295] OF Byte)));   {CCB memory }
  19776.                                                                { for driver}
  19777.      {Write max size(CCB) = 296; all other calls = 150}
  19778.      END;
  19779.  
  19780. _______________________________________________________________________________
  19781.  
  19782. »AppleTalk Session Protocol Functions
  19783.  
  19784. This section contains descriptions of the .XPP driver functions that you can call. 
  19785. Each function description shows the required parameter block fields, their offsets
  19786. within the parameter block and a brief definition of the field.  Possible result
  19787. codes are also described.
  19788.  
  19789. »Note on Result Codes
  19790.  
  19791. An important distinction exists between the aspParamErr and aspSessClose  result
  19792. codes that may be returned by the .XPP driver.
  19793.  
  19794. When the driver returns aspParamErr to a call that takes as an input a session reference
  19795. number, the session reference number does not relate to a valid open session.  There
  19796. could be several reasons for this, such as the workstation or server end closed the
  19797. session or the server end of the session died.
  19798.  
  19799. The aspSessClosed result code indicates that even though the session reference number
  19800. relates to a valid session, that particular session is in the process of closing down
  19801. (although  the session is not yet closed).
  19802.  
  19803. FUNCTION ASPOpenSession (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  19804.  
  19805. Parameter block
  19806.   -->    26    csCode       word       Always ASPOpenSess
  19807.   -->    28    sessRefnum   word       Session reference number
  19808.   -->    30    aspTimeout   byte       Retry interval in seconds
  19809.   -->    31    aspRetry     byte       Number of retries
  19810.   -->    32    serverAddr   long word  Server socket address
  19811.   -->    36    scbPointer   pointer    Pointer to session control block
  19812.   -->    40    attnRoutine  pointer    Pointer to attention routine
  19813.  
  19814. ASPOpenSession initiates (opens) a session between the workstation and a server.  The
  19815. required parameter block is shown above.  A brief definition of the fields follows.
  19816.  
  19817. SessRefnum is a unique number identifying the open session between the workstation
  19818. and the server.  The SessRefnum is returned when the function completes successfully
  19819. and is used in all calls to identify the session.
  19820.  
  19821. ASPTimeOut is the interval in seconds between retries of the open session request.
  19822.  
  19823. ASPRetry is the number of retries that will be attempted.
  19824.  
  19825. ServerAddr is the network identifier or address of the socket on which the server is
  19826. listening.
  19827.  
  19828. SCBPointer points to a nonrelocatable block of data for the session control block
  19829. (SCB) that the .XPP driver reserves for use in maintaining an open session.   The SCB
  19830. size is defined by the constant scbMemSize.  The SCB is a locked block and as long as
  19831. the session is open, the SCB cannot be modified in any way by the application.  There
  19832. is one SCB for each open session.  This block can be reused when a CloseSess call is
  19833. issued and completed for that session, or when the session is indicated as closed
  19834. through return of aspParamErr as the result of a call for that session.
  19835.  
  19836. AttnRoutine is a pointer to a routine that is invoked if an attention from the server
  19837. is received, or upon session closing.  If this pointer is equal to zero, no attention
  19838. routine will be invoked.
  19839.  
  19840. Result codes    aspNoMoreSess    Driver cannot support another session
  19841.                 aspParamErr      Server returned bad (positive) error code    
  19842.                 aspNoServers     No servers at that address, or the server
  19843.                                  did not respond to the request
  19844.                 reqAborted       OpenSess was aborted by an AbortOS
  19845.                 aspBadVersNum    Server cannot support the offered 
  19846.                                  version number
  19847.                 aspServerBusy    Server cannot open another session
  19848.  
  19849. Note: The number of sessions that the driver is capable of supporting
  19850.       depends on the machine that the driver is running on. 
  19851.  
  19852. FUNCTION ASPCloseSession (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  19853.  
  19854. Parameter block
  19855.   -->    26    csCode      word  Always ASPCloseSession
  19856.   -->    28    sessRefnum  word  Session reference number
  19857.  
  19858. ASPCloseSession closes the session identified by the sessRefnum returned in the
  19859. ASPOpenSession call.  ASPCloseSession aborts any calls that are active on the session,
  19860. closes the session, and calls the attention routine, if any, with an attention code
  19861. of zero (zero is invalid as a real attention code).
  19862.  
  19863. Result codes    aspParamErr      Parameter error, indicates an invalid
  19864.                                  session reference number
  19865.                 aspSessClosed    Session already in process of closing
  19866.  
  19867. FUNCTION ASPAbortOS (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  19868.  
  19869. Parameter block
  19870.   -->    26    csCode            word     Always ASPAbortOS
  19871.   -->    28    abortSCBPointer   pointer  Pointer to session control block
  19872.  
  19873. ASPAbortOS aborts a pending (not yet completed) ASPOpenSession call.  The aborted
  19874. ASPOpenSession call will return a reqAborted error.
  19875.  
  19876. AbortSCBPointer points to the original SCB used in the the pending ASPOpenSession
  19877. call.
  19878.  
  19879. Result codes    cbNotFound    SCB not found, no outstanding open session
  19880.                               to be aborted.
  19881.                               Pointer did not point to an open session SCB.
  19882.  
  19883. FUNCTION ASPGetParms (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
  19884.  
  19885. Parameter block
  19886.   -->    26    csCode          word  Always ASPGetParms
  19887.   -->    28    aspMaxCmdSize   word  Maximum size of command block
  19888.   -->    30    aspQuantumSize  word  Maximum data size
  19889.   -->    32    numSesss        word  Number of sessions
  19890.  
  19891. ASPGetParms returns three ASP parameters.  This call does not require an open session.
  19892.  
  19893. ASPMaxCmdSize is the maximum size of a command that can be sent to the server.
  19894.  
  19895. ASPQuantumSize is the maximum size of data that can be transferred to the server in a
  19896. Write request or from the server in a command reply.
  19897.  
  19898. NumSess is the number of concurrent sessions supported by the driver.
  19899.  
  19900. FUNCTION ASPCloseAll (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  19901.  
  19902. Parameter block
  19903.   -->    26    csCode  word  Always ASPCloseAll
  19904.  
  19905. ASPCloseAll closes every session that the driver has active, aborting all active
  19906. requests and invoking the attention routines where provided.  This call should be
  19907. used carefully.  ASPCloseAll can be used as a system level resource for making sure
  19908. all sessions are closed prior to closing the driver.
  19909.  
  19910. FUNCTION ASPUserWrite (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
  19911.  
  19912. Parameter block
  19913.   -->    18    cmdResult   long word  ASP command result
  19914.   -->    26    csCode      word       Always UserWrite
  19915.   -->    28    sessRefnum  word       Session reference number
  19916.   -->    30    aspTimeout  byte       Retry interval in seconds
  19917.   -->    32    cbSize      word       Command block size
  19918.   -->    34    cbPtr       pointer    Command block pointer
  19919.   <->    38    rbSize      word       Reply buffer size and reply size
  19920.   -->    40    rbPtr       pointer    Reply buffer pointer
  19921.   <->    44    wdSize      word       Write data size
  19922.   -->    46    wdPtr       pointer    Write data pointer
  19923.   -->    50    ccbStart    record     Start of memory for CCB
  19924.  
  19925. ASPUserWrite transfers data on a session.  ASPUserWrite is one of the two main calls
  19926. that can be used to transfer data on an ASP session.  The other call that performs a
  19927. similar data transfer  is ASPUserCommand described below.  The ASPUserWrite command
  19928. returns data in two different places.  Four bytes of data are returned in the cmdResult
  19929. field and a variable size reply buffer is also returned.
  19930.  
  19931. CmdResult is four bytes of data returned by the server.
  19932.  
  19933. SessRefnum is the session reference number returned in the ASPOpenSession call.
  19934.  
  19935. ASPTimeOut is the interval in seconds between retries of the call.  Notice that there
  19936. is no aspRetry field (retries are infinite).  The command will be retried at the
  19937. prescribed interval until completion or the session is closed.
  19938.  
  19939. CBSize is the size in bytes of the command data that is to be written on the session.
  19940.  The size of the command block must not exceed the value of aspMaxCmdSize returned by
  19941. the ASPGetParms call. Note that this buffer is not the data to be written by the
  19942. command but only the data of the command itself.
  19943.  
  19944. CBPtr points to the command data.
  19945.  
  19946. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  19947. command.  RBSize is also returned and indicates the size of the reply that was actually
  19948. returned.
  19949.  
  19950. RBPtr points to the reply buffer.
  19951.  
  19952. WDSize is passed and indicates the size of the write data in bytes to be sent by the
  19953. command.  WDSize is also returned and indicates the size of the write data that was
  19954. actually written.
  19955.  
  19956. WDPointer points to the write data buffer.
  19957.  
  19958. CCBStart is the start of the memory to be used by the .XPP driver for the command
  19959. control block.  The size of this block is equal to a maximum of 296 bytes.  To determine
  19960. the exact requirement, refer to the CCB Sizes section of this document.
  19961.  
  19962. Result codes     aspParamErr       Invalid session number, session has
  19963.                                    been closed
  19964.                  aspSizeErr        Command block size is bigger than MaxCmdSize
  19965.                  aspSessClosed     Session is closing
  19966.                  aspBufTooSmall    Reply is bigger than response buffer;
  19967.                                    the buffer will be filled, data will
  19968.                                    be truncated
  19969.  
  19970. FUNCTION ASPUserCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  19971.  
  19972. Parameter block
  19973.   -->    18    cmdResult   long word  ASP command result
  19974.   -->    26    csCode      word       Always ASPUserCommand
  19975.   -->    28    sessRefnum  word       Session number
  19976.   -->    30    aspTimeout  byte       Retry interval in seconds
  19977.   -->    32    cbSize      word       Command block size
  19978.   -->    34    cbPtr       pointer    Command block pointer
  19979.   <->    38    rbSize      word       Reply buffer and reply size
  19980.   -->    40    rbPtr       pointer    Reply buffer pointer
  19981.   -->    50    ccbStart    record     Start of memory for CCB
  19982.  
  19983. ASPUserCommand is used to send a command to the server on a session.
  19984.  
  19985. SessRefnum is the session reference number returned in the ASPOpenSession call.
  19986.  
  19987. ASPTimeOut is the interval in seconds between retries of the call.  Notice that there
  19988. is no aspRetry field (retries are infinite).  The command will be retried at the
  19989. prescribed interval until completion or the session is closed.
  19990.  
  19991. CBSize is the size in bytes of the block of data that contains the command to be sent
  19992. to the server on the session.  The size of the command block must not exceed the
  19993. value of aspMaxCmdSize returned by the ASPGetParms call.
  19994.  
  19995. CBPointer points to the block of data containing the command that is to be sent to
  19996. the server on the session.
  19997.  
  19998. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  19999. command.  RBSize is also returned and indicates the size of the reply that was actually
  20000. returned.
  20001.  
  20002. RBPtr points to the reply buffer.
  20003.  
  20004. CCBStart is the start of the memory to be used by the .XPP driver for the command
  20005. control block.  The size of this block is equal to a maximum of 150 bytes.  To determine
  20006. the exact requirement refer to the CCB Sizes section of this document.
  20007.  
  20008. Result codes     aspParamErr       Invalid session number, session has
  20009.                                    been closed
  20010.                  aspSizeErr        Command block size is bigger than MaxCmdSize
  20011.                  aspSessClosed     Session is closing
  20012.                  aspBufTooSmall    Reply is bigger than response buffer;
  20013.                                    the buffer will be filled, data will
  20014.                                    be truncated
  20015.  
  20016. FUNCTION ASPGetStatus (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  20017.  
  20018. Parameter block
  20019.   -->    26    csCode      word       Always ASPGetStatus
  20020.   -->    30    aspTimeout  byte       Retry interval in seconds
  20021.   -->    31    aspRetry    byte       Number of retries
  20022.   -->    32    serverAddr  long word  Server socket address
  20023.   <->    38    rbSize      word       Reply buffer and reply size
  20024.   -->    40    rbPtr       pointer    Reply buffer pointer
  20025.   -->    50    ccbStart    record     Start of memory for CCB
  20026.  
  20027. ASPGetStatus returns server status.  This call is also used as GetServerInfo at the
  20028. AFP level. This call is unique in that it transfers data over the network without
  20029. having a session open.  This call does not pass any data but requests that server
  20030. status be returned.
  20031.  
  20032. ASPTimeOut is the interval in seconds between retries of the call.
  20033.  
  20034. ASPRetry is the number of retries that will be attempted.
  20035.  
  20036. ServerAddr is the network identifier or address of the socket on which the server is
  20037. listening.
  20038.  
  20039. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  20040. command. RBSize is also returned and indicates the size of the reply that was actually
  20041. returned.
  20042.  
  20043. RBPtr points to the reply buffer.
  20044.  
  20045. CCBStart is the start of the memory to be used by the .XPP driver for the command
  20046. control block.  The size of this block is equal to a maximum of 150 bytes.  To determine
  20047. the exact requirement refer to the CCB Sizes section of this document.
  20048.  
  20049. Result codes    aspBufTooSmall    Reply is bigger than response buffer,
  20050.                                   or Replysize is bigger than ReplyBuffsize
  20051.                 aspNoServer       No response from server at address used
  20052.                                   in call
  20053.  
  20054. _______________________________________________________________________________
  20055.  
  20056. »AFP Implementation
  20057.  
  20058. The AFPCall function (called AFPCommand in Pascal) passes a command to an AFP server.
  20059.  The first byte of the AFPCall command buffer (the AFP command byte) must contain a
  20060. valid AFP command code.
  20061.  
  20062. Note:  Server information should be gotten through an ASPGetStatus call
  20063.        (described above).  ASPGetStatus is equivalent to the AFPGetSrvrInfo.
  20064.        Making an AFP GetSrvrInfo call using AFPCommand results in an error.
  20065.  
  20066. »Mapping AFP Commands
  20067.  
  20068. Most AFP calls are implemented by XPP through a very simple one-to-one mapping of an
  20069. AFP call to an ASP call without interpretation or verification of the data.
  20070.  
  20071. The .XPP driver maps AFP command codes to ASP commands according to the following
  20072. conventions:
  20073.  
  20074.   AFP Command Code     Comment
  20075.  
  20076.   $00                  Invalid AFP command
  20077.   $01–$BE (1–190)      Mapped to UserCommand  (with the exceptions
  20078.                        listed below)
  20079.   $BF (191)            Mapped to UserCommand  (Reserved for developers;
  20080.                        will never be used by Apple)
  20081.   $C0–$FD (192–253)    Mapped to UserWrite
  20082.   $FE (254)            Mapped to UserWrite  (will never be used by Apple)
  20083.   $FF (255)            Invalid AFP command
  20084.  
  20085. The following AFP calls are exceptions to the above conventions:
  20086.  
  20087.   AFP Command (Code/Decimal)  Comment
  20088.  
  20089.   getSrvrInfo (15)            Mapped to ASPGetStatus  (Use ASPGetStatus
  20090.                               to make this call)
  20091.   login (18)                  Mapped to appropriate log-in dialog including
  20092.                               ASPOpenSession call
  20093.   loginCont (19)              Mapped to appropriate log-in dialog
  20094.   logout (20)                 Mapped to ASPCloseSession
  20095.   write (33)                  Mapped to ASPUserWrite
  20096.  
  20097. The following AFP calls can pass or return more data than can fit in quantumSize
  20098. bytes (eight ATP response packets) and may be broken up by XPP into multiple ASP
  20099. calls.
  20100.  
  20101.   AFP Command (Code/Decimal)  Comment
  20102.  
  20103.   read (27)                   Can return up to the number of bytes
  20104.                               indicated in reqCount
  20105.   write (33)                  Can pass up to the number of bytes
  20106.                               indicated in reqCount
  20107.  
  20108. »AFPCall Function
  20109.  
  20110. The AFPCall function can have one of the following command formats.
  20111.  
  20112.   •  General
  20113.   •  Login
  20114.   •  AFPWrite
  20115.   •  AFPRead
  20116.  
  20117. »General Command Format
  20118.  
  20119. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  20120.  
  20121. Parameter block
  20122.   -->    18    cmdResult   long word  AFP command result
  20123.   -->    26    csCode      word       Always AFPCall
  20124.   -->    28    sessRefnum  word       Session reference number
  20125.   -->    30    aspTimeout  byte       Retry interval in seconds
  20126.   -->    32    cbSize      word       Command buffer size
  20127.   -->    34    cbPtr       pointer    Command buffer
  20128.   <->    38    rbSize      word       Reply buffer size and reply size
  20129.   -->    40    rbPtr       pointer    Reply buffer pointer
  20130.   <->    44    wdSize      word       Write data size
  20131.   -->    46    wdPtr       pointer    Write data pointer
  20132.   -->    50    ccbStart    record     Start of memory for CCB
  20133.  
  20134. The general command format for the AFPCall function passes an AFP command to the
  20135. server.  This format is used for all AFP calls except AFPLogin, AFPRead, and AFPWrite.
  20136.   Note that from Pascal this call is referred to as AFPCommand.
  20137.  
  20138. CmdResult is four bytes of data returned from the server containing an indication of
  20139. the result of the AFP command.
  20140.  
  20141. SessRefnum is the session reference number returned in the AFPLogin call.
  20142.  
  20143. ASPTimeOut is the interval in seconds between retries of the call by the driver.
  20144.  
  20145. CBSize is the size in bytes of the block of data that contains the command to be sent
  20146. to the server on the session. The size of the command block must not exceed the value
  20147. of aspMaxCmdSize returned by the ASPGetParms call.
  20148.  
  20149. CBPtr points to start of the block of data (command block) containing the command
  20150. that is to be sent to the server on the session.  The first byte of the command block
  20151. must contain the AFP command byte.  Subsequent bytes in the command buffer contain
  20152. the  parameters associated with the command as defined in the AFP document.
  20153.  
  20154. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  20155. command. RBSize is also returned and indicates the size of the reply that was actually
  20156. returned.
  20157.  
  20158. RBPtr points to the reply buffer.
  20159.  
  20160. WDSize is the size of data to be written to the server (only used if the command is
  20161. one that is mapped to an ASPUserWrite).
  20162.  
  20163. WDPtr points to the write data buffer (only used if the command is one that is mapped
  20164. to an ASPUserWrite).
  20165.  
  20166. CCBStart is the start of the memory to be used by the .XPP driver for the command
  20167. control block.  The size of this block is equal to a maximum of 296 bytes.  To determine
  20168. the exact requirement refer to the CCB Sizes section of this document.
  20169.  
  20170. Result codes    aspParamErr       Invalid session number; session has
  20171.                                   been closed
  20172.                 aspSizeErr        Command block size is bigger than MaxCmdSize
  20173.                 aspSessClosed     Session is closing
  20174.                 aspBufTooSmall    Reply is bigger than response buffer or
  20175.                                   buffer will be filled, data will be truncated
  20176.                 afpParmError      AFP command block size is equal to zero.
  20177.                                   This error will also be returned if the
  20178.                                   command byte in the command block is equal
  20179.                                   to 0 or $FF (255) or GetSrvrStatus (15).
  20180.  
  20181. »Login Command Format
  20182.  
  20183. The AFP login command executes a series of AFP operations as defined in the AFP Draft
  20184. Proposal.  For further information, refer to the AFP document.
  20185.  
  20186. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
  20187.  
  20188. Parameter block
  20189.   -->    18    cmdResult       long word  AFP command result
  20190.   -->    26    csCode          word       Always AFPCall
  20191.   -->    28    sessRefnum      word       Session reference number
  20192.   -->    30    aspTimeout      byte       Retry interval in seconds
  20193.   -->    31    aspRetry        byte       Number of retries
  20194.   -->    32    cbSize          word       Command buffer size
  20195.   -->    34    cbPtr           pointer    Command buffer
  20196.   <->    38    rbSize          word       Reply buffer size and reply size
  20197.   -->    40    rbPtr           pointer    Reply buffer pointer
  20198.   -->    44    afpAddrBlock    long word  Server address block
  20199.   <->    48    afpSCBPtr       pointer    SCB pointer
  20200.   <->    52    afpAttnRoutine  pointer    Attention routine pointer
  20201.   -->    50    ccbStart        record     Start of command control block
  20202.  
  20203. CmdResult is four bytes of data returned from the server containing an indication of
  20204. the result of the AFP command.
  20205.  
  20206. SessRefnum is the session reference number (returned by the AFPLogin call).
  20207.  
  20208. ASPTimeOut is the interval in seconds between retries of the call.
  20209.  
  20210. ASPRetry is the number of retries that will be attempted.
  20211.  
  20212. CBSize is the size in bytes of the block data that contains the command to be sent to
  20213. the server on the session. The size of the command block must not exceed the value of
  20214. aspMaxCmdSize returned by the ASPGetParms call.
  20215.  
  20216. CBPtr points to the block of data (command block) containing the AFP login command
  20217. that is to be sent to the server on the session.  The first byte of the command block
  20218. must be the AFP login command byte.  Subsequent bytes in the command buffer contain
  20219. the parameters associated with the command.
  20220.  
  20221. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  20222. command.  RBSize is also returned and indicates the size of the reply that was actually
  20223. returned.
  20224.  
  20225. RBPtr points to the reply buffer.
  20226.  
  20227. AFPServerAddr is the network identifier or address of the socket on which the server
  20228. is listening.
  20229.  
  20230. AFPSCBPointer points to a locked block of data for the session control block
  20231. (SCB). The SCB size is defined by scbMemSize.  The SCB is a locked block, and as long
  20232. as the session is open, the SCB cannot be modified in any way by the application. 
  20233. There is one SCB for each open session.
  20234.  
  20235. AFPAttnRoutine is a pointer to a routine that is invoked if an attention from the
  20236. server is received.  When afpAttnRoutine is equal to zero, no attention routine will
  20237. be invoked.
  20238.  
  20239. CCBStart is the start of the memory to be used by the .XPP driver for the command
  20240. control block.  The size of this block is equal to a maximum of 150 bytes.  To determine
  20241. the exact requirement refer to the CCB Sizes section later in this chapter.
  20242.  
  20243. Note:  In the parameter block, the afpSCBPointer and the afpAttnRoutine
  20244.        fields overlap with the start of the CCB and are modified by the call.
  20245.  
  20246. Result codes    aspSizeErr        Command block size is bigger than MaxCmdSize
  20247.                 aspBufTooSmall    Reply is bigger than response buffer or
  20248.                                   buffer will be filled, data will be truncated
  20249.                 aspNoServer       Server not responding
  20250.                 aspServerBusy     Server cannot open another session
  20251.                 aspBadVersNum     Server cannot support the offered ASP
  20252.                                   version number
  20253.                 aspNoMoreSess     Driver cannot support another session.
  20254.  
  20255. »AFPWrite Command Format
  20256.  
  20257. The AFPWrite and AFPRead command formats allow the calling application to make AFP-level
  20258. calls that read or write a data block that is larger than a single ASP-level call is
  20259. capable of reading or writing.  The maximum number of bytes of data that can be read
  20260. or written at the ASP level is equal to quantumSize.
  20261.  
  20262. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  20263.  
  20264. Parameter block
  20265.   -->    18    cmdResult   long word  AFP command result
  20266.   -->    26    csCode      word       Always AFPCall
  20267.   -->    28    sessRefnum  word       Session number
  20268.   -->    30    aspTimeout  byte       Retry interval in seconds
  20269.   -->    32    cbSize      word       Command buffer size
  20270.   -->    34    cbPtr       pointer    Command buffer
  20271.   <->    38    rbSize      word       Reply buffer size and reply size
  20272.   -->    40    rbPtr       pointer    Reply buffer pointer
  20273.   -->    44    wdSize      word       (used internally)
  20274.   <->    46    wdPtr       pointer    Write data pointer  (updated)
  20275.   -->    50    ccbStart    record     Start of memory for CCB
  20276.  
  20277. CmdResult is four bytes of data returned from the server containing an indication of
  20278. the result of the AFP command.
  20279.  
  20280. SessRefnum is the session reference number returned in the AFPLogin call.
  20281.  
  20282. ASPTimeOut is the interval in seconds between retries of the call.
  20283.  
  20284. CBSize is the size in bytes of the block data that contains the command to be sent to
  20285. the server on the session.  The size of the command block must not exceed the value
  20286. of aspMaxCmdSize returned by the aspGetParms call.
  20287.  
  20288. CBPtr points to the block of data (see command block structure below) containing the
  20289. AFP write command that is to be sent to the server on the session.  The first byte of
  20290. the Command Block must contain the AFP write command byte.
  20291.  
  20292. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  20293. command.  RBSize is also returned and indicates the size of the reply that was actually
  20294. returned.
  20295.  
  20296. RBPtr points to the reply buffer.
  20297.  
  20298. WDSize is used internally.
  20299.  
  20300. Note:  This command does not pass the write data size in the queue element
  20301.        but in the command buffer.  XPP will look for the size in that buffer.
  20302.  
  20303. WDPtr is a pointer to the block of data to be written.  Note that this field will be
  20304. updated by XPP as it proceeds and will always point to that section of the data which
  20305. XPP is currently writing.
  20306.  
  20307. CCBStart is the start of the memory to be used by the XPP driver for the command
  20308. control block.  The size of this block is equal to a maximum of 296 bytes.  To determine
  20309. the exact requirement refer to the CCB Sizes section later in this chapter.
  20310.  
  20311. Command Block Structure:  The AFP write command passes several arguments to XPP in
  20312. the command buffer itself. The byte offsets are relative to the location pointed to
  20313. by cbPtr.
  20314.  
  20315.   -->    0    cmdByte       byte       AFP call command byte
  20316.   -->    1    startEndFlag  byte       Start/end Flag
  20317.   <->    4    rwOffset      long word  Offset within fork to write
  20318.   <->    8    reqCount      long word  Requested count
  20319.  
  20320. CmdByte is the AFP call command byte and must contain the AFP write command code.
  20321.  
  20322. StartEndFlag is a one-bit flag (the high bit of the byte) indicating whether the
  20323. rwOffset field is relative to the beginning or the end of the fork (all other bits
  20324. are zero).
  20325.  
  20326.   0 = relative to the beginning of the fork
  20327.   1 = relative to the end of the fork
  20328.  
  20329. RWOffset is the byte offset within the fork at which the write is to begin.
  20330.  
  20331. ReqCount indicates the size of the data to be written and is returned as the actual
  20332. size written.
  20333.  
  20334. The rwOffset and reqCount fields are modified by XPP as the write proceeds and will
  20335. always indicate the current value of these fields.
  20336.  
  20337. The Pascal structure of the AFP command buffer follows:
  20338.  
  20339. AFPCommandBlock = PACKED RECORD
  20340.                     cmdByte:       Byte;
  20341.                     startEndFlag:  Byte;
  20342.                     forkRefNum:    INTEGER;    {used by server}
  20343.                     rwOffset:      LONGINT;
  20344.                     reqCount:      LONGINT;
  20345.                     newLineFlag:   Byte;       {unused by write}
  20346.                     newLineChar:   CHAR;       {unused by write}
  20347.                   END;
  20348.  
  20349. Result codes    aspParamErr       Invalid session number
  20350.                 aspSizeErr        Command block size is bigger than MaxCmdSize
  20351.                 aspSessClosed     Session is closing
  20352.                 aspBufTooSmall    Reply is bigger than response buffer
  20353.  
  20354. »AFPRead Command Format
  20355.  
  20356. The AFPWrite and AFPRead command formats allow the calling application to make AFP-level
  20357. calls that read or write a data block that is larger than a single ASP-level call is
  20358. capable of reading or writing.  The maximum number of bytes of data that can be read
  20359. or written at the ASP level is equal to quantumSize.
  20360.  
  20361. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  20362.  
  20363. Parameter block
  20364.   -->    18    cmdResult   long word  ASP command result
  20365.   -->    26    csCode      word       Always AFPCall
  20366.   -->    28    sessRefnum  word       Session number
  20367.   -->    30    aspTimeout  byte       Retry interval in seconds
  20368.   -->    32    cbSize      word       Command buffer size
  20369.   -->    34    cbPtr       pointer    Command buffer
  20370.   -->    38    rbSize      word       Used internally
  20371.   <->    40    rbPtr       pointer    Reply buffer pointer (updated)
  20372.   -->    50    ccbStart    record     Start of memory for CCB
  20373.  
  20374. CmdResult is four bytes of data returned from the server containing an indication of
  20375. the result of the AFP command.
  20376.  
  20377. SessRefnum is the session reference number returned in the AFPLogin  call.
  20378.  
  20379. ASPTimeOut is the interval in seconds between retries of the call.
  20380.  
  20381. CBSize is the size in bytes of the block data that contains the command to be sent to
  20382. the server on the session.  The size of the command block must not exceed the value
  20383. of aspMaxCmdSize returned by the GetParms call.
  20384.  
  20385. CBPtr points to the block of data (command block) containing the AFP read command
  20386. that is to be sent to the server on the session.  The first byte of the command block
  20387. must contain the AFP read command byte.  The command block structure is shown below.
  20388.  
  20389. RBSize  is used internally.
  20390.  
  20391. Note:  This command does not pass the read size in the queue element but
  20392.        in the command buffer.  XPP will look for the size in that buffer.
  20393.  
  20394. RBPtr points to the reply buffer.  Note that this field will be updated by XPP as it
  20395. proceeds and will always point to that section of the buffer that XPP is currently
  20396. reading into.
  20397.  
  20398. CCBStart is the start of the memory to be used by the .XPP driver for the command
  20399. control block.  The size of this block is equal to a maximum of 150 bytes.  To determine
  20400. the exact requirement refer to The CCB Sizes section later in this chapter.
  20401.  
  20402. Command Block Structure:  The AFP read command passes several arguments to XPP in the
  20403. command buffer itself. The byte offsets are relative to the location pointed to by
  20404. cbPointer.
  20405.  
  20406.   -->    0    cmdByte      byte       AFP call command byte
  20407.   <->    4    rwOffset     long word  Offset within fork to read
  20408.   <->    8    reqCount     long word  Requested count
  20409.   -->    12   newLineFlag  byte       Newline Flag
  20410.   -->    13   newLineChar  byte       Newline Character
  20411.  
  20412. CmdByte is the AFP call command byte and must contain the AFP read command code.
  20413.  
  20414. RWOffset is the byte offset within the fork at which the read is to begin.
  20415.  
  20416. ReqCount  indicates the size of the read data buffer and is returned as the actual
  20417. size read.
  20418.  
  20419. The rwOffset and reqCount fields are modified by XPP as the read proceeds and will
  20420. always indicate the current value of these fields.
  20421.  
  20422. NewLineFlag is a one-bit flag (the high bit of the byte) indicating whether or not
  20423. the read is to terminate at a specified character (all other bits are zero).
  20424.  
  20425.   0 = no Newline Character is specified
  20426.   1 = a Newline Character is specified
  20427.  
  20428. NewLineChar is any character from $00 to $FF (inclusive) that, when encountered in
  20429. reading the fork, causes the read operation to terminate.
  20430.  
  20431. The Pascal structure of the AFPCommand follows:
  20432.  
  20433. AFPCommandBlock = PACKED RECORD
  20434.                     cmdByte:       Byte;
  20435.                     startEndFlag:  Byte;     {unused for read}
  20436.                     forkRefNum:    INTEGER;  {used by server}
  20437.                     rwOffset:      LONGINT;
  20438.                     reqCount:      LONGINT;
  20439.                     newLineFlag:   Byte;
  20440.                     newLineChar:   CHAR;
  20441.                   END;
  20442.  
  20443. Result codes    aspParamErr       Invalid session number
  20444.                 aspSizeErr        Command block size is bigger than MaxCmdSize
  20445.                 aspSessClosed     Session is closing
  20446.                 aspBufTooSmall    Reply is bigger than response buffer
  20447.  
  20448. _______________________________________________________________________________
  20449.  
  20450. »CCB Sizes
  20451.  
  20452. The .XPP driver uses the memory provided at the end of the UserWrite, UserCommand,
  20453. and GetStatus functions parameter blocks as an internal command control block (CCB).
  20454. Using the maximum block sizes specified in the call descriptions will provide adequate
  20455. space for the call to execute successfully. However, this section is provided for
  20456. developers who wish to minimize the amount of memory taken up by the CCB in the queue
  20457. element.
  20458.  
  20459. Specifically, this memory is used for building data structures to be used in making
  20460. calls to the ATP driver.  This includes parameter blocks and buffer data structures
  20461. (BDS). The structure of the BDS is detailed in elsewhere in this chapter.  The exact
  20462. size of this memory depends on the size of the response expected, and, in the case of
  20463. UserWrite, on the size of data to be written.
  20464.  
  20465. In the UserCommand and GetStatus cases (along with all AFP calls which map to UserCommand),
  20466. a BDS must be set up to hold the response information.  The number of entries in this
  20467. BDS is equal to the size of the response buffer divided by the maximum number of data
  20468. bytes per ATP response packet (578), rounded up.  As described in the ASP chapter in
  20469. Inside AppleTalk, ASP must ask for an extra response in the case where the response
  20470. buffer is an exact multiple of 578.  Of course, no BDS can be larger than eight
  20471. elements.  XPP also needs bytes for the queue element to call ATP with, so the minimum
  20472. size of a CCB, as a function of the response buffer size (rbSize) is
  20473.  
  20474.   bdsSize = MIN (((rbSize DIV 578) + 1),8) * bdsEntrySz
  20475.   ccbSize = ioQElSize + 4 + bdsSize
  20476.  
  20477. With UserWrite (and AFP calls mapping to UserWrite), XPP must create an additional
  20478. BDS and queue element to use in sending the write data to the server.  Therefore the 
  20479. minimum size of a UserWrite CCB, as a function of the response buffer and write data
  20480. sizes (rbSize and wdSize) is:
  20481.  
  20482.   wrBDSSize = MIN (((wdSize DIV 578) + 1),8) * bdsEntrySz
  20483.   wrCCBSize = (2 * ioQElSize) + 4 + bdsSize + wrBDSSize
  20484.  
  20485. Note: BDSEntrySz is equal to 12; ioQelSize is equal to 50.
  20486.  
  20487. _______________________________________________________________________________
  20488.  
  20489. ».XPP Driver Result Codes
  20490.  
  20491. Result Code       Comment                                      Returned by
  20492.  
  20493. aspBadVersNum     Server cannot support the offered version    ASPOpenSession
  20494.                   number.                                      AFPCall (Login)
  20495.  
  20496. aspBufTooSmall    Reply is bigger than response buffer.        ASPUserWrite
  20497.                   Buffer will be filled, data may be           ASPUserCommand
  20498.                   truncated.                                   ASPGetStatus
  20499.                                                                AFPCall
  20500.  
  20501. aspNoMoreSess     Driver cannot support another session.       ASPOpenSessION 
  20502.                                                                AFPCall (Login)
  20503.  
  20504. aspNoServers      No servers at that address.                  ASPGetStatus
  20505.                   The server did not respond to the request.   ASPOpenSession
  20506.                                                                AFPCall (Login)
  20507.  
  20508. aspParamErr       Parameter error, server returned bad         ASPOpenSession 
  20509.                   (positive) error code.                       ASPCloseSess
  20510.                   Invalid Session Reference Number.            ASPUserWrite
  20511.                                                                ASPUserCommand
  20512.                                                                AFPCall
  20513.  
  20514. aspServerBusy     Server cannot open another session.          ASPOpenSession
  20515.                                                                AFPCall (Login)
  20516.  
  20517. aspSessClosed     Session already in process of closing.       ASPCloseSession
  20518.                                                                ASPUserWrite
  20519.                                                                ASPUserCommand
  20520.                                                                AFPCall
  20521.  
  20522. aspSizeErr        Command block size is bigger than            ASPUserWrite
  20523.                   maxParamSize.                                ASPUserCommand
  20524.                                                                AFPCall
  20525.  
  20526. cbNotFound        SCB not found, no outstanding                ASPAbortOS
  20527.                   open session to be aborted.  Pointer did
  20528.                   not point to an open session SCB.
  20529.  
  20530. afpParmError      AFP Command Block size is less than or       AFPCall
  20531.                   equal to zero.  Command byte in the
  20532.                   Command block is equal to 0 or $FF (255)
  20533.                   or GetSrvrStatus (15).
  20534.  
  20535. reqAborted        Open session was aborted by an               ASPOpenSession
  20536.                   Abort Open Session.                          AFPCall (Login)
  20537.  
  20538. _______________________________________________________________________________
  20539.  
  20540.  
  20541. æKY Protocol…Handlers…and…Socket…Listeners
  20542. æC »PROTOCOL HANDLERS AND SOCKET LISTENERS                   AppleTalkManager
  20543. _______________________________________________________________________________
  20544.  
  20545. This section describes how to write your own protocol handlers and socket listeners.
  20546. If you’re only interested in using the default protocol handlers and socket listeners
  20547. provided by the Pascal interface, you can skip this section. Protocol handlers and
  20548. socket listeners must be written in assembly language because they’ll be called by
  20549. the .MPP driver with parameters in various registers not directly accessible from
  20550. Pascal.
  20551.  
  20552. The .MPP and .ATP drivers have been designed to maximize overall throughput while
  20553. minimizing code size. Two principal sources of loss of throughput are unnecessary
  20554. buffer copying and inefficient mechanisms for dispatching (routing) packets between
  20555. the various layers of the network protocol architecture. The AppleTalk Manager completely
  20556. eliminates buffer copying by using simple, efficient dispatching mechanisms at two
  20557. important points of the data reception path:  protocol handlers and socket listeners.
  20558. To write your own, you should understand the flow of control in this path.
  20559.  
  20560. _______________________________________________________________________________
  20561.  
  20562. »Data Reception in the AppleTalk Manager
  20563.  
  20564. When the SCC detects an ALAP frame addressed to the particular node (or a broadcast
  20565. frame), it interrupts the Macintosh’s MC68000. An interrupt handler built into the
  20566. .MPP driver gets control and begins servicing the interrupt. Meanwhile, the frame’s
  20567. ALAP header bytes are coming into the SCC’s data reception buffer; this is a three-byte
  20568. FIFO buffer. The interrupt handler must remove these bytes from the SCC’s buffer to
  20569. make room for the bytes right behind; for this purpose, MPP has an internal buffer,
  20570. known as the Read Header Area (RHA), into which it places these three bytes.
  20571.  
  20572. The third byte of the frame contains the ALAP protocol type field. If the most significant
  20573. bit of this field is set (that is, ALAP protocol types 128 to 255), the frame is an
  20574. ALAP control frame. Since ALAP control frames are only three bytes long (plus two CRC
  20575. bytes), for such frames the interrupt handler simply confirms that the CRC bytes
  20576. indicate an error-free frame and then performs the specified action.
  20577.  
  20578. If, however, the frame being received is a data frame (that is, ALAP protocol types 1
  20579. to 127), intended for a higher layer of the protocol architecture implemented on that
  20580. Macintosh, this means that additional data bytes are coming right behind. The interrupt
  20581. handler must immediately pass control to the protocol handler corresponding to the
  20582. protocol type specified in the third byte of the ALAP frame for continued reception
  20583. of the frame. To allow for such a dispatching mechanism, the ALAP code in MPP maintains
  20584. a protocol table. This consists of a list of currently used ALAP protocol types with
  20585. the memory addresses of their corresponding protocol handlers. To allow MPP to transfer
  20586. control to a protocol handler you’ve written, you must make an appropriate entry in
  20587. the protocol table with a valid ALAP protocol type and the memory address of your
  20588. code module.
  20589.  
  20590. To enter your protocol handler into the protocol table, issue the LAPOpenProtocol
  20591. call from Pascal or an AttachPH call from assembly language. Thereafter, whenever an
  20592. ALAP header with your ALAP protocol type is received, MPP will call your protocol
  20593. handler. When you no longer wish to receive packets of that ALAP protocol type, call
  20594. LAPCloseProtocol from Pascal or DetachPH from assembly language.
  20595.  
  20596. Warning:  Remember that ALAP protocol types 1 and 2 are reserved by DDP
  20597.           for the default protocol handler and that types 128 to 255 are
  20598.           used by ALAP for its control frames.
  20599.  
  20600. A protocol handler is a piece of assembly-language code that controls the reception
  20601. of AppleTalk packets of a given ALAP protocol type. More specifically, a protocol
  20602. handler must carry out the reception of the rest of the frame following the ALAP
  20603. header. The nature of a particular protocol handler depends on the characteristics of
  20604. the protocol for which it was written. In the simplest case, the protocol handler
  20605. simply reads the entire packet into an internal buffer. A more sophisticated protocol
  20606. handler might read in the header of its protocol, and on the basis of information
  20607. contained in it, decide where to put the rest of the packet’s data. In certain cases,
  20608. the protocol handler might, after examining the header corresponding to its own
  20609. protocol, in turn transfer control to a similar piece of code at the next-higher
  20610. level of the protocol architecture (for example, in the case of DDP, its protocol
  20611. handler must call the socket listener of the datagram’s destination socket).
  20612.  
  20613. In this way, protocol handlers are used to allow “on the fly” decisions regarding the
  20614. intended recipient of the packets’s data, and thus avoid buffer copying. By using
  20615. protocol handlers and their counterparts in higher layers
  20616. (for instance, socket listeners), data sent over the AppleTalk network is read directly
  20617. from the network into the destination’s buffer.
  20618.  
  20619. _______________________________________________________________________________
  20620.  
  20621. »Writing Protocol Handlers
  20622.  
  20623. When the .MPP driver calls your protocol handler, it has already read the first five
  20624. bytes of the packet into the RHA. These are the three-byte ALAP header and the next
  20625. two bytes of the packet. The two bytes following the header must contain the length
  20626. in bytes of the data in the packet, including these two bytes themselves, but excluding
  20627. the ALAP header.
  20628.  
  20629. Note:  Since ALAP packets can have at most 600 data bytes, only the lower
  20630.        ten bits of this length value are significant.
  20631.  
  20632. After determining how many bytes to read and where to put them, the protocol handler
  20633. must call one or both of two functions that perform all the low-level manipulation of
  20634. the SCC required to read bytes from the network. ReadPacket can be called repeatedly
  20635. to read in the packet piecemeal or ReadRest can be called to read the rest of the
  20636. packet. Any number of ReadPacket calls can be used, as long as a ReadRest call is
  20637. made to read the final piece of the packet. This is necessary because ReadRest restores
  20638. state information and verifies that the hardware-generated CRC is correct. An error
  20639. will be returned if the protocol handler attempts to use ReadPacket to read more
  20640. bytes than remain in the packet.
  20641.  
  20642. When MPP passes control to your protocol handler, it passes various parameters and
  20643. pointers in the processor’s registers:
  20644.  
  20645.   Register(s)    Contents
  20646.  
  20647.   A0-A1          SCC addresses used by MPP
  20648.   A2             Pointer to MPP’s local variables (discussed below)
  20649.   A3             Pointer to next free byte in RHA
  20650.   A4             Pointer to ReadPacket and ReadRest jump table
  20651.   D1 (word)      Number of bytes left to read in packet
  20652.  
  20653. These registers, with the exception of A3, must be preserved until ReadRest is called.
  20654. A3 is used as an input parameter to ReadPacket and ReadRest, so its contents may be
  20655. changed. D0, D2, and D3 are free for your use. In addition, register A5 has been
  20656. saved by MPP and may be used by the protocol handler until ReadRest is called. When
  20657. control returns to the protocol handler from ReadRest, MPP no longer needs the data
  20658. in these registers. At that point, standard interrupt routine conventions apply and
  20659. the protocol handler can freely use
  20660. A0-A3 and D0-D3 (they’re restored by the interrupt handler).
  20661.  
  20662. D1 contains the number of bytes left to be read in the packet as derived from the
  20663. packet’s length field. A transmission error could corrupt the length field or some
  20664. bytes in the packet might be lost, but this won’t be discovered until the end of the
  20665. packet is reached and the CRC checked.
  20666.  
  20667. When the protocol handler is first called, the first five bytes of the packet
  20668. (ALAP destination node ID, source node ID, ALAP protocol type, and length) can be
  20669. read from the RHA. Since A3 is pointing to the next free position in the RHA, these
  20670. bytes can be read using negative offsets from A3. For instance, the ALAP source node
  20671. ID is at –4(A3), the packet’s data length (given in D1) is also pointed to by –2(A3),
  20672. and so on. Alternatively, they can be accessed as positive offsets from the top of
  20673. the RHA. The effective address of the top of the RHA is toRHA(A2), so the following
  20674. code could be used to obtain the ALAP type field:
  20675.  
  20676.   LEA       toRHA(A2),A5      ;A5 points to top of RHA
  20677.   MOVE.B    lapType(A5),D2    ;load D2 with type field
  20678.  
  20679. These methods are valid only as long as SCC interrupts remain locked out (which they
  20680. are when the protocol handler is first called). If the protocol handler lowers the
  20681. interrupt level, another packet could arrive over the network and invalidate the
  20682. contents of the RHA.
  20683.  
  20684. •••Refer to Technical Note #201:•••
  20685.  
  20686. You can call ReadPacket by jumping through the jump table in the following way:
  20687.  
  20688.   JSR (A4)
  20689.  
  20690.   On entry    D3:    number of bytes to be read (word)
  20691.               A3:    pointer to a buffer to hold the bytes
  20692.   On exit     D0:    modified
  20693.               D1:    number of bytes left to read in packet (word)
  20694.               D2:    preserved
  20695.               D3:    =  0 if requested number of bytes were read
  20696.                      <> 0 if error
  20697.               A0-A2: preserved
  20698.               A3:    pointer to one byte past the last byte read
  20699.  
  20700. ReadPacket reads the number of bytes specified in D3 into the buffer pointed to by
  20701. A3. The number of bytes remaining to be read in the packet is returned in D1. A3
  20702. points to the byte following the last byte read.
  20703.  
  20704. You can call ReadRest by jumping through the jump table in the following way:
  20705.  
  20706.   JSR 2(A4)
  20707.  
  20708.   On entry    A3:    pointer to a buffer to hold the bytes
  20709.               D3:    size of the buffer (word)
  20710.   On exit     D0-D1: modified
  20711.               D2:    preserved
  20712.               D3:    = 0 if packet was exactly the size of the buffer
  20713.                      < 0 if packet was (–D3) bytes too large to fit in
  20714.                          buffer and was truncated
  20715.                      > 0 if D3 bytes weren't read (packet is smaller
  20716.                          than buffer)
  20717.               A0-A2: preserved
  20718.               A3:    pointer to one byte past the last byte read
  20719.  
  20720. ReadRest reads the remaining bytes of the packet into the buffer whose size is given
  20721. in D3 and whose location is pointed to by A3. The result of the operation is returned
  20722. in D3.
  20723.  
  20724. ReadRest can be called with D3 set to a buffer size greater than the packet size;
  20725. ReadPacket cannot (it will return an error).
  20726.  
  20727. Warning:  Remember to always call ReadRest to read the last part of a
  20728.           packet; otherwise the system will eventually crash.
  20729.  
  20730. If at any point before it has read the last byte of a packet, the protocol handler
  20731. wants to discard the remaining data, it should terminate by calling ReadRest as
  20732. follows:
  20733.  
  20734.   MOVEQ    #0,D3    ;byte count of 0
  20735.   JSR      2(A4)    ;call ReadRest
  20736.   RTS
  20737.  
  20738. Or, equivalently:
  20739.  
  20740.   MOVEQ    #0,D3    ;byte count of 0
  20741.   JMP      2(A4)    ;JMP to ReadRest, not JSR
  20742.  
  20743. In all other cases, the protocol handler should end with an RTS, even if errors were
  20744. detected. If MPP returns an error from a ReadPacket call, the protocol handler must
  20745. quit via an RTS without calling ReadRest at all (in this case it has already been
  20746. called by MPP).
  20747.  
  20748. The Z (Zero) condition code is set upon return from these routines to indicate the
  20749. presence of errors (CRC, overrun, and so on). Zero bit set means no error was detected;
  20750. a nonzero condition code implies an error of some kind.
  20751.  
  20752. Up to 24 bytes of temporary storage are available in MPP’s RHA. When the protocol
  20753. handler is called, 19 of these bytes are free for its use. It may read several bytes
  20754. (at least four are suggested) into this area to empty the SCC’s buffer and buy some
  20755. time for further processing.
  20756.  
  20757. MPP’s globals include some variables that you may find useful. They’re allocated as a
  20758. block of memory pointed to by the contents of the global variable ABusVars, but a
  20759. protocol handler can access them by offsets from A2:
  20760.  
  20761.   Name          Contents
  20762.  
  20763.   sysLAPAddr    This node’s node ID (byte)
  20764.   toRHA         Top of the Read Header Area (24 bytes)
  20765.   sysABridge    Node ID of a bridge (byte)
  20766.   sysNetNum     This node’s network number (word)
  20767.   vSCCEnable    Status Register (SR) value to re-enable SCC interrupts (word)
  20768.  
  20769. Warning:  Under no circumstances should your protocol handler modify
  20770.           these variables. It can read them to find the node’s ID, its
  20771.           network number, and the node ID of a bridge on the AppleTalk internet.
  20772.  
  20773. If, after reading the entire packet from the network and using the data in the RHA,
  20774. the protocol handler needs to do extensive post-processing, it can load the value in
  20775. vSCCEnable into the SR to enable interrupts. To allow your programs to run transparently
  20776. on any Macintosh, use the value in vSCCEnable rather than directly manipulating the
  20777. interrupt level by changing specific bits in the SR.
  20778.  
  20779. Additional information, such as the driver’s version number or reference number and a
  20780. pointer (or handle) to the driver itself, may be obtained from MPP’s device control
  20781. entry. This can be found by dereferencing the handle in the unit table’s entry corresponding
  20782. to unit number 9; for more information, see the section “The Structure of a Device
  20783. Driver” in the Device Manager chapter.
  20784.  
  20785. »Timing Considerations
  20786.  
  20787. Once it’s been called by MPP, your protocol handler has complete responsibility for
  20788. receiving the rest of the packet. The operation of your protocol handler is time-critical.
  20789. Since it’s called just after MPP has emptied the SCC’s three-byte buffer, the protocol
  20790. handler has approximately 95 microseconds (best case) before it must call ReadPacket
  20791. or ReadRest. Failure to do so will result in an overrun of the SCC’s buffer and loss
  20792. of packet information. If, within that time, the protocol handler can’t determine
  20793. where to put the entire incoming packet, it should call ReadPacket to read at least
  20794. four bytes into some private buffer (possibly the RHA). Doing this will again empty
  20795. the SCC’s buffer and buy another 95 microseconds. You can do this as often as necessary,
  20796. as long as the processing time between successive calls to ReadPacket doesn’t exceed
  20797. 95 microseconds.
  20798.  
  20799. _______________________________________________________________________________
  20800.  
  20801. »Writing Socket Listeners
  20802.  
  20803. A socket listener is a piece of assembly-language code that receives datagrams delivered
  20804. by the DDP built-in protocol handler and delivers them to the client owning that
  20805. socket.
  20806.  
  20807. When a datagram (a packet with ALAP protocol type 1 or 2) is received by the ALAP,
  20808. DDP’s built-in protocol handler is called. This handler reads the DDP header into the
  20809. RHA, examines the destination socket number, and determines whether this socket is
  20810. open by searching DDP’s socket table. This table lists the socket number and corresponding
  20811. socket listener address for each open socket. If an entry is found matching the
  20812. destination socket, the protocol handler immediately transfers control to the appropriate
  20813. socket listener. (To allow DDP to recognize and branch to a socket listener you’ve
  20814. written, call DDPOpenSocket from Pascal or OpenSkt from assembly language.)
  20815.  
  20816. At this point, the registers are set up as follows:
  20817.  
  20818.   Register(s)    Contents
  20819.  
  20820.   A0-A1          SCC addresses used by MPP
  20821.   A2             Pointer to MPP’s local variables (discussed above)
  20822.   A3             Pointer to next free byte in RHA
  20823.   A4             Pointer to ReadPacket and ReadRest jump table
  20824.   D0             This packet’s destination socket number (byte)
  20825.   D1             Number of bytes left to read in packet (word)
  20826.  
  20827. The entire ALAP and DDP headers are in the RHA; these are the only bytes of the
  20828. packet that have been read in from the SCC’s buffer. The socket listener can get the
  20829. destination socket number from D0 to select a buffer into which the packet can be
  20830. read. The listener then calls ReadPacket and ReadRest as described under “Writing
  20831. Protocol Handlers” above. The timing considerations discussed in that section apply
  20832. as well, as do the issues related to accessing the MPP local variables.
  20833.  
  20834. The socket listener may examine the ALAP and DDP headers to extract the various
  20835. fields relevant to its particular client’s needs. To do so, it must first examine the
  20836. ALAP protocol type field (three bytes from the beginning of the RHA) to decide whether
  20837. a short (ALAP protocol type=1) or long (ALAP protocol type=2) header has been received.
  20838.  
  20839. A long DDP header containing a nonzero checksum field implies that the datagram was
  20840. checksummed at the source. In this case, the listener can recalculate the checksum
  20841. using the received datagram, and compare it with the checksum value. The following
  20842. subroutine can be used for this purpose:
  20843.  
  20844.   DoChksum    ;
  20845.               ; D1 (word) = number of bytes to checksum
  20846.               ; D3 (word) = current checksum
  20847.               ; A1 points to the bytes to checksum
  20848.               ;
  20849.               CLR.W     D0          ;clear high byte
  20850.               SUBQ.W    #1,D1       ;decrement count for DBRA
  20851.   Loop        MOVE.B    (A1)+,D0    ;read a byte into D0
  20852.               ADD.W     D0,D3       ;accumulate checksum
  20853.               ROL.W     #1,D3       ;rotate left one bit
  20854.               DBRA      D1,Loop     ;loop if more bytes
  20855.               RTS
  20856.  
  20857. Note:  D0 is modified by DoChksum.
  20858.  
  20859. The checksum must be computed for all bytes starting with the DDP header byte following
  20860. the checksum field up to the last data byte (not including the CRC bytes). The socket
  20861. listener must start by first computing the checksum for the DDP header fields in the
  20862. RHA. This is done as follows:
  20863.  
  20864.               CLR.W     D3          ;set checksum to 0
  20865.               MOVEQ     #ddpHSzLong-ddpDstNet,D1
  20866.                                     ;length of header part to checksum
  20867.               LEA       toRHA+lapHdSz+ddpDstNet(A2),A1
  20868.                                     ;point to destination network number
  20869.               JSR       DoChksum
  20870.               ; D3 = accumulated checksum of DDP header part
  20871.  
  20872. The socket listener must now continue to set up D1 and A1 for each subsequent portion
  20873. of the datagram, and call DoChksum for each. It must not alter the value in D3.
  20874.  
  20875. The situation of the calculated checksum being equal to 0 requires special attention.
  20876. For such packets, the source sends a value of –1 to distinguish them from unchecksummed
  20877. packets. At the end of its checksum computation, the socket listener must examine the
  20878. value in D3 to see if it’s 0. If so, it’s converted to –1 and compared with the
  20879. received checksum to determine whether there was a checksum error:
  20880.  
  20881.               TST.W     D3          ;is calculated value 0?
  20882.               BNE.S     @1          ;no -- go and use it
  20883.               SUBQ.W    #1,D3       ;it is 0; make it -1
  20884.   @1          CMP.W     toRHA+lapHdSz+ddpChecksum(A2),D3
  20885.               BNE       ChksumError
  20886.  
  20887. _______________________________________________________________________________
  20888.  
  20889.  
  20890. æKY Summary…of…the…AppleTalk…Manager
  20891. æC »SUMMARY OF THE APPLETALK MANAGER                         AppleTalkManager
  20892. _______________________________________________________________________________
  20893.  
  20894. Constants
  20895.  
  20896. CONST
  20897.   lapSize = 20;   {ABusRecord size for ALAP}
  20898.   ddpSize = 26;   {ABusRecord size for DDP}
  20899.   nbpSize = 26;   {ABusRecord size for NBP}
  20900.   atpSize = 56;   {ABusRecord size for ATP}
  20901.  
  20902. _______________________________________________________________________________
  20903.  
  20904. Data Types
  20905.  
  20906. TYPE
  20907.   ABProtoType = (lapProto,ddpProto,nbpProto,atpProto);
  20908.   ABRecHandle = ^ABRecPtr;
  20909.   ABRecPtr    = ^ABusRecord;
  20910.   ABusRecord  =
  20911.     RECORD
  20912.        abOpcode:        ABCallType;    {type of call}
  20913.        abResult:        INTEGER;       {result code}
  20914.        abUserReference: LONGINT;       {for your use}
  20915.        CASE ABProtoType OF
  20916.          lapProto:
  20917.           (lapAddress:  LAPAdrBlock; {destination or source node ID}
  20918.            lapReqCount: INTEGER;     {length of frame data or buffer size in }
  20919.                                      { bytes}
  20920.            lapActCount  INTEGER;     {number of frame data bytes actually }
  20921.                                      { received}
  20922.            lapDataPtr:  Ptr);        {pointer to frame data or pointer to }
  20923.                                      { buffer}
  20924.          ddpProto:
  20925.           (ddpType:     Byte;        {DDP protocol type}
  20926.            ddpSocket:   Byte;        {source or listening socket number}
  20927.            ddpAddress:  AddrBlock;   {destination or source socket address}
  20928.            ddpReqCount: INTEGER;     {length of datagram data or buffer size }
  20929.                                      { in bytes}
  20930.            ddpActCount: INTEGER;     {number of bytes actually received}
  20931.            ddpDataPtr:  Ptr;         {pointer to buffer}
  20932.            ddpNodeID:   Byte);       {original destination node ID}
  20933.          nbpProto:
  20934.           (nbpEntityPtr:     EntityPtr;    {pointer to entity name}
  20935.            nbpBufPtr:        Ptr;          {pointer to buffer}
  20936.            nbpBufSize:       INTEGER;      {buffer size in bytes}
  20937.            nbpDataField:     INTEGER;      {number of addresses or socket }
  20938.                                            { number}
  20939.            nbpAddress:       AddrBlock;    {socket address}
  20940.            nbpRetransmitInfo:RetransType); {retransmission information}
  20941.         atpProto:
  20942.          (atpSocket:     Byte;       {listening or responding socket number}
  20943.           atpAddress:    AddrBlock;  {destination or source socket address}
  20944.           atpReqCount:   INTEGER;    {request size or buffer size}
  20945.           atpDataPtr     Ptr;        {pointer to buffer}
  20946.           atpRspBDSPtr:  BDSPtr;     {pointer to response BDS}
  20947.           atpBitMap:     BitMapType; {transaction bit map}
  20948.           atpTransID:    INTEGER;    {transaction ID}
  20949.           atpActCount:   INTEGER;    {number of bytes actually received}
  20950.           atpUserData:   LONGINT;    {user bytes}
  20951.           atpXO:         BOOLEAN;    {exactly-once flag}
  20952.           atpEOM:        BOOLEAN;    {end-of-message flag}
  20953.           atpTimeOut:    Byte;       {retry timeout interval in seconds}
  20954.           atpRetries:    Byte;       {maximum number of retries}
  20955.           atpNumBufs:    Byte;       {number of elements in response BDS or }
  20956.                                      { number of response packets sent}
  20957.           atpNumRsp:     Byte;       {number of response packets received or }
  20958.                                      { sequence number}
  20959.           atpBDSSize:    Byte;       {number of elements in response BDS}
  20960.           atpRspUData:   LONGINT;    {user bytes sent or received in }
  20961.                                      { transaction response}
  20962.           atpRspBuf:     Ptr;        {pointer to response message buffer}
  20963.           atpRspSize:    INTEGER);   {size of response message buffer}
  20964.     END;
  20965.  
  20966.   ABCallType = (tLAPRead,tLAPWrite,tDDPRead,tDDPWrite,tNBPLookup,tNBPConfirm,
  20967.                 tNBPRegister,tATPSndRequest,tATPGetRequest,tATPSdRsp,tATPAddRsp,
  20968.                 tATPRequest,tATPResponse);
  20969.  
  20970.   LAPAdrBlock = PACKED RECORD
  20971.                   dstNodeID:    Byte;   {destination node ID}
  20972.                   srcNodeID:    Byte;   {source node ID}
  20973.                   lapProtType:  ABByte  {ALAP protocol type}
  20974.                 END;
  20975.  
  20976.   ABByte = 1..127; {ALAP protocol type}
  20977.   AddrBlock = PACKED RECORD
  20978.                 aNet:     INTEGER;  {network number}
  20979.                 aNode:    Byte;     {node ID}
  20980.                 aSocket:  Byte      {socket number}
  20981.               END;
  20982.  
  20983.   BDSPtr     = ^BDSType;
  20984.   BDSType    = ARRAY[0..7] OF BDSElement; {response BDS}
  20985.   BDSElement = RECORD
  20986.                  buffSize:   INTEGER;  {buffer size in bytes}
  20987.                  buffPtr:    Ptr;      {pointer to buffer}
  20988.                  dataSize:   INTEGER;  {number of bytes actually received}
  20989.                  userBytes:  LONGINT   {user bytes}
  20990.                END;
  20991.  
  20992.   BitMapType = PACKED ARRAY[0..7] OF BOOLEAN;
  20993.   EntityPtr  = ^EntityName;
  20994.   EntityName = RECORD
  20995.                  objStr:   Str32;  {object}
  20996.                  typeStr:  Str32;  {type}
  20997.                  zoneStr:  Str32    {zone}
  20998.                END;
  20999.  
  21000.   Str32 = STRING[32];
  21001.   RetransType =
  21002.       PACKED RECORD
  21003.         retransInterval:  Byte;  {retransmit interval in 8-tick units}
  21004.         retransCount:     Byte   {total number of attempts}
  21005.       END;
  21006.  
  21007.   MPPParamBlock = PACKED RECORD
  21008.        qLink:          QElemPtr;     {next queue entry}
  21009.        qType:          INTEGER;      {queue type}
  21010.        ioTrap:         INTEGER;      {routine trap}
  21011.        ioCmdAddr:      Ptr;          {routine address}
  21012.        ioCompletion:   ProcPtr;      {completion routine}
  21013.        ioResult:       OSErr;        {result code}
  21014.        ioNamePtr:      StringPtr;    {command result (ATP user bytes) [long]}
  21015.        ioVRefNum:      INTEGER;      {volume reference or drive number}
  21016.        ioRefNum:       INTEGER;      {driver reference number}
  21017.        csCode:         INTEGER;      {call command code AUTOMATICALLY SET}
  21018.  
  21019.        CASE MPPParmType OF
  21020.        LAPWriteParm:
  21021.                     (filler0:INTEGER;
  21022.                     wdsPointer:Ptr);    {->Write Data Structure}
  21023.        AttachPHParm,DetachPHParm:
  21024.                     (protType:Byte;     {ALAP Protocol Type}
  21025.                     filler1:Byte;
  21026.                     handler:Ptr);       {->protocol handler routine}
  21027.        OpenSktParm,CloseSktParm,WriteDDPParm:
  21028.                     (socket:Byte;       {socket number}
  21029.                     checksumFlag:Byte;  {checksum flag}
  21030.                     listener:Ptr);      {->socket listener routine}
  21031.        RegisterNameParm,LookupNameParm,ConfirmNameParm,RemoveNameParm:
  21032.                     (interval:Byte;     {retry interval}
  21033.                     count:Byte;         {retry count}
  21034.                     entityPtr:Ptr;      {->names table element or }
  21035.                                         { ->entity name}
  21036.                     CASE MPPParmType OF
  21037.                     RegisterNameParm:
  21038.                              (verifyFlag:Byte;     {set if verify needed}
  21039.                               filler3:Byte);
  21040.                     LookupNameParm:
  21041.                                     (retBuffPtr:Ptr;       {->return buffer}
  21042.                                     retBuffSize:INTEGER;   {return buffer size}
  21043.                                     maxToGet:INTEGER;      {matches to get}
  21044.                                     numGotten:INTEGER);    {matched gotten}
  21045.                     ConfirmNameParm:
  21046.                                     (confirmAddr:AddrBlock; {->entity}
  21047.                                     newSocket:Byte;         {socket number}
  21048.                                     filler4:Byte));
  21049.  
  21050.        SetSelfSendParm:
  21051.                     (newSelfFlag:Byte;  {self-send toggle flag}
  21052.                     oldSelfFlag:Byte);  {previous self-send state}
  21053.        KillNBPParm:
  21054.                     (nKillQEl:Ptr);     {ptr to Q element to cancel}
  21055.      END;
  21056.  
  21057. ATPParamBlock = PACKED RECORD
  21058.          qLink:            QElemPtr;    {next queue entry}
  21059.          qType:            INTEGER;     {queue type}
  21060.          ioTrap:           INTEGER;     {routine trap}
  21061.          ioCmdAddr:        Ptr;         {routine address}
  21062.          ioCompletion:     ProcPtr;     {completion routine}
  21063.          ioResult:         OSErr;       {result code}
  21064.          userData:         LONGINT;     {ATP user bytes [long]}
  21065.          reqTID:           INTEGER;     {request transaction ID}
  21066.          ioRefNum:         INTEGER;     {driver reference number
  21067.          csCode:           INTEGER;     {Call command code }
  21068.                                         { AUTOMATICALLY SET}
  21069.          atpSocket:        Byte;        {currBitMap or socket number}
  21070.          atpFlags:         Byte;        {control information}
  21071.          addrBlock:        AddrBlock;   {source/dest. socket address}
  21072.          reqLength:        INTEGER;     {request/response length}
  21073.          reqPointer:       Ptr;         {-> request/response data}
  21074.          bdsPointer:       Ptr;         {-> response BDS}
  21075.          CASE MPPParmType OF
  21076.                 SendRequestParm,NSendRequestParm:
  21077.                     (numOfBuffs:Byte;   {numOfBuffs}
  21078.                     timeOutVal:Byte;    {timeout interval}
  21079.                     numOfResps:Byte;    {number responses actually received}
  21080.                     retryCount:Byte;    {number of retries}
  21081.                     intBuff:INTEGER);   {used internally for NSendRequest}
  21082.                 SendResponseParm:
  21083.                     (filler0:Byte;      {number of responses being sent}
  21084.                     bdsSize:Byte;       {number of BDS elements}
  21085.                     transID:INTEGER);   {transaction ID}
  21086.                 GetRequestParm:
  21087.                     (bitMap:Byte;       {bit map}
  21088.                     filler1:Byte);
  21089.                 AddResponseParm:
  21090.                     (rspNum:Byte;       {sequence number}
  21091.                     filler2:Byte);
  21092.                 KillSendReqParm,KillGetReqParm:
  21093.                     (aKillQEl:Ptr);     {ptr to Q element to cancel}
  21094.          END;
  21095.  
  21096.   XPPParamBlock = PACKED RECORD
  21097.     qLink:         QElemPtr;  {next queue entry}
  21098.     qType:         INTEGER;   {queue type}
  21099.     ioTrap:        INTEGER;   {routine trap}
  21100.     ioCmdAddr:     Ptr;       {routine address}
  21101.     ioCompletion:  ProcPtr;   {completion routine}
  21102.     ioResult:      OSErr;     {result code}
  21103.     cmdResult:     LONGINT;   {command result (ATP user bytes) [long]}
  21104.     ioVRefNum:     INTEGER;   {volume reference or drive number)
  21105.     ioRefNum:      INTEGER;   {driver reference number)
  21106.     csCode:        INTEGER;   {Call command code}
  21107.     CASE XPPPrmBlkType OF
  21108.       ASPAbortPrm:
  21109.         (abortSCBPtr:    Ptr);      {SCB pointer for AbortOS [long]}
  21110.       ASPSizeBlk:
  21111.         (aspMaxCmdSize:  INTEGER;   {for SPGetParms [word]
  21112.         aspQuantumSize:  INTEGER;   {for SPGetParms [word]}
  21113.         numSesss:        INTEGER);  {for SPGetParms [word]}
  21114.       XPPPrmBlk:
  21115.         (sessRefnum:     INTEGER;   {offset to session refnum [word]}
  21116.         aspTimeout:      Byte;      {timeout for ATP [byte]}
  21117.         aspRetry:        Byte;      {retry count for ATP [byte]}
  21118.         CASE XPPSubPrmType OF
  21119.           ASPOpenPrm:
  21120.             (serverAddr:    AddrBlock;  {server address block [longword]}
  21121.             scbPointer:     Ptr;        {SCB pointer [longword]}
  21122.             attnRoutine:    Ptr);       {attention routine pointer [long]}
  21123.           ASPSubPrm:
  21124.             (cbSize:        INTEGER;    {command block size [word]}
  21125.             cbPtr:          Ptr;        {command block pointer [long]}
  21126.             rbSize:         INTEGER;    {reply buffer size [word]}
  21127.             rbPtr:          Ptr;        {reply buffer pointer [long]}
  21128.             CASE XPPEndPrmType OF
  21129.               AFPLoginPrm:
  21130.                 (afpAddrBlock:     AddrBlock;    {address block in}
  21131.                                                  { AFPlogin [long]}
  21132.                 afpSCBPtr:         Ptr;          {SCB pointer in }
  21133.                                                  { AFPlogin [long]}
  21134.                 afpAttnRoutine:    Ptr);         {attn routine pointer }
  21135.                                                  { in AFPlogin}
  21136.               ASPEndPrm:
  21137.                 (wdSize:           INTEGER;      {write data size [word]}
  21138.                 wdPtr:             Ptr;          {write data pointer [long]}
  21139.                 ccbStart:          ARRAY[0..295] OF Byte)));   {CCB memory }
  21140.                                                                { for driver}
  21141.      {Write max size(CCB) = 296; all other calls = 150}
  21142.      END;
  21143.  
  21144. AFPCommandBlock = PACKED RECORD
  21145.                     cmdByte:       Byte;
  21146.                     startEndFlag:  Byte;
  21147.                     forkRefNum:    INTEGER;    {used by server}
  21148.                     rwOffset:      LONGINT;
  21149.                     reqCount:      LONGINT;
  21150.                     newLineFlag:   Byte;       {unused by write}
  21151.                     newLineChar:   CHAR;       {unused by write}
  21152.                   END;
  21153.  
  21154. AFPCommandBlock = PACKED RECORD
  21155.                     cmdByte:       Byte;
  21156.                     startEndFlag:  Byte;     {unused for read}
  21157.                     forkRefNum:    INTEGER;  {used by server}
  21158.                     rwOffset:      LONGINT;
  21159.                     reqCount:      LONGINT;
  21160.                     newLineFlag:   Byt